MySQL事务隔离级别
参考自:https://dev.mysql.com/doc/refman/5.6/en/innodb-transaction-isolation-levels.html
第一部分:概述 InnoDB遵循SQL:1992标准,提供READ UNCOMMITTED, READ COMMITTED, REPEATABLE READ和SERIALIZABLE四种事务隔离级别。InnoDB默认使用的事务隔离级别是REPEATABLE READ。 用户可以自己修改会话或全局级别的事务隔离级别,语法如下:SET [GLOBAL | SESSION] TRANSACTION transaction_characteristic [, transaction_characteristic] ... transaction_characteristic: ISOLATION LEVEL level | READ WRITE | READ ONLY level: REPEATABLE READ | READ COMMITTED | READ UNCOMMITTED | SERIALIZABLE你也可以在启动时添加--transaction-isolation启动项或者将其写入配置文件,来设置相应的全局事务隔离级别。 READ UNCOMMITTED, READ COMMITTED, REPEATABLE READ和SERIALIZABLE这四种事务隔离级别所提供的事务一致性是越来越强的,但是并发性却是却来越差的。 第二部分:事务隔离级别 提到事务隔离级别就必须先明确以下三种读:
脏读:读到了其他事务已修改但未提交的数据 不可重复读:由于其他事务的修改,导致同一事务中两次查询读到的数据不同 幻读:由于其他事务的修改,导致同一事务中两次查询读到的记录数不同1.READ UNCOMMITTED 这种隔离级别下普通select语句是不加事务锁的,因此会产生脏读,这种事务隔离级别是应当完全避免的。除select语句以外的其他语句加锁模式与READ COMMITTED一样。 2.READ COMMITTED 同REPEATABLE READ一样,这种隔离级别下也实现了一致性非锁定读,但区别在于此隔离级别下的一致性读是语句级的,即只能避免脏读,不能避免不可重复读和幻读。其实现方式大致是:
- 一致性非锁定读的select语句检测要锁定的索引记录上是否有独占锁(在server层也会添加S模式的record lock,此锁为server层的元数据库锁,非innodb事务锁)。
- 如果有独占锁那么到undo中寻找最近的前镜像。
- 如果没有独占锁那么直接读取数据。
时刻一,A会话执行:select * from T2 where id=1;
时刻二,A会话执行:start transaction; select * from T1; --snapshot建立
时刻三,B会话执行:针对T1表和T2表的DML语句修改数据
时刻四,A会话执行:select * from T1; --发现读到的数据与时刻二一模一样,证明表T1实现了一致性读
时刻五,A会话执行:select * from T2 where id=1; --发现读到的数据与时刻一一致,证明snapshot非表级,而是库级
- 对唯一索引的访问只会添加record lock,而不会使用gap lock(即也没有next-key lock)。
- 对非唯一索引的访问使用gap lock或者next-key lock,如果访问的记录不存在就是gap lock,否则就是next-key lock。
更多精彩