首页 » 读书笔记 » 《高性能MySQL》——事务

《高性能MySQL》——事务

事务就是一组原子性的SQL查询

  • ACID 表示
    1. 原子性(atomicity),一个事务必须被视为一个不可分割的最小单元,要么全部成功,要么全部失败回滚。
    2. 一致性(consistency),数据库总是从一个一致性状态转换到另一个一致性状态。
    3. 隔离性(isolation),一个事务所做的修改在最终提交前,对其他事务是不可见的。
    4. 持久性(durability),一旦事务提交,则其所做的修改就会永久保存到数据库中。

事务也会跟锁一样,增加开销

隔离级别

在SQL标准中定义了四种隔离级别,每一种都规定了一个事务中所做的修改,哪些在事务内和事务间是可见的,哪些是不可见的。较低级别的隔离通常可以执行更高的并发,系统开销也更低。

  • 四种隔离级别
    1. READ UNCOMMITTED(未提交读) 事务中的修改,即使没提交,对其他事务也是可见的,事务可以读取未提交的数据,这也被成为 脏读(dirty read),一般很少使用。
    2. READ COMMITTED (提交读) 大多数据库系统的默认隔离级别,但MySQL不是,一个事务从开始到提交前,所做的任何修改对其他事务都是不可见的。也叫不可重复读,两次同样的查询可能会得到不一样的结果。
    3. REPEATABLE READ(可重复读) 解决了脏读的问题。同一事务中多次读取同样记录的结果是一致的。但无法解决 幻读(当某个事务在读取某个范围内的记录时,另外一个事务又在该范围内插入了新纪录,当之前的事务再次读取该范围的记录时,会产生幻行),是MySQL的默认事务隔离级别。(InnoDB和XtraDB存储引擎通过多版本并发控制解决了幻读问题)
    4. SERIALIZABLE(可串行化) 强制事务串行执行,会在读取的每一行数据上都加锁,可能导致大量的超时和锁挣用的问题。

死锁

死锁是指两个或者多个事务在同一资源上相互占用,并请求锁定对方占用的资源,从而导致恶性循环的现象。

为解决这种问题,数据库系统实现了各种死锁检测和死锁超时机制。

InnoDB目前处理死锁的方法是,将持有最少行级排他锁的事务进行回滚。

事务日志

事务日志可以帮助提高事务的效率。使用事务日志,存储引擎在修改表的数据时只需要修改其内存拷贝,再把该修改行为记录到持久在硬盘上的事务日志中,而不用每次都将修改的数据本身持久到磁盘。事务日志采用的事追加的方式,因此写日志的操作是磁盘上一小块区域内的循序 I/O,而不像随机 I/O 需要在磁盘的多个地方移动磁头,所以采用事务日志的方式相对来说要快得多,事务日志持久化后,内存中被修改的数据在后台可以慢慢的刷回到磁盘。

MySQL中的事务

自动提交(AUTO COMMIT)

MySQL默认采用自动提交模式,每个查询都被当做已给事务进行提交操作。修改AUTO COMMIT 对非事务型的表,比如MyISAM或者内存表,不会有任何影响。

还有一些命令,在执行之前会强制执行 COMMIT 提交当前的活动事务。(ALTER TABLE、LOCK TABLES)

通过执行 SET TRANSACTION ISOLATION LEVEL 命令来设置隔离级别。

在事务中混合使用存储引擎

MySQL服务器层不管理事务,事务是由下层的存储引擎实现的。所以在同一个事务中,使用多种存储引擎是不可靠的。

隐式和显示锁定

InnoDB 采用的是两阶段锁定协议(two-phase locking protocol)。在事务执行过程中,随时都可以执行锁定,锁只有在执行 COMMIT 和 ROLLBACK 的时候才会释放,并且所有的锁是在同一时刻被释放。前面描述的锁定都是隐式锁定,InnoDB 会根据隔离级别在需要的时候自动加锁。

InnoDB也支持通过特定的语句进行显示锁定,这些语句不属于 SQL 规范。

  • SELECT … LOCK IN SHARE MODE
  • SELECT … FOR UPDATE

原文链接:《高性能MySQL》——事务,转载请注明来源!

0