本文主要介绍InnoDB的:锁定读和一致性非锁定读html
在一个事务中查询数据时,普通的SELECT语句不会对查询的数据进行加锁,其余事务仍能够对查询的数据执行更新和删除操做。所以,InnoDB提供了两种类型的锁定读来保证额外的安全性:mysql
SELECT ... LOCK IN SHARE MODE: 对读取的行添加S锁,其余事物能够对这些行添加S锁,若添加X锁,则会被阻塞。sql
SELECT ... FOR UPDATE: 会对查询的行及相关联的索引记录加X锁,其余事务请求的S锁或X锁都会被阻塞。数据库
当事务提交或回滚后,经过这两个语句添加的锁都会被释放。安全
注意:只有在自动提交被禁用时,SELECT FOR UPDATE才能够锁定行,若开启自动提交,则匹配的行不会被锁定。session
MySQL官方文档对弈一致性读的定义:并发
A consistent read means that InnoDB uses multi-versioning to present to a query a snapshot of the database at a point in time.版本控制
就是说:一致性读意味着InnoDB使用多版本控制来实现一个查询,这个查询所依赖的数据是基于某个时间点的数据库快照
。code
注意:是数据库的快照,而不是要查询的那个表的快照。htm
在事务隔离级别设置为READ COMMITTED和REPEATABLE READ时,默认状况下InnoDB是经过一致性读来处理SELECT语句的。一致性读不会对它访问的表设置任何锁,所以,在一个表上进行一致性读的同时,其余session能够随意修改这些表。
一致性读是使用基于时间点的快照信息来呈现查询结果的读取操做,而无论其余事务在同一时间产生的变动。若是查询的数据已被其余事务改变,InnoDB会基于undo log的内容来重建最初的数据。
两种事务隔离级别下,读取的快照数据的区别:
该事务中第一个一致性读创建的快照
。经过提交当前事务并发起一个新的查询,能够看获得新的快照。本次一致性读创建的快照
。(即,快照的时间点是基于本次一致性读的时间点,也就是最新的数据)假设当前事务隔离级别为REPEATABLE READ,当发出一个一致性读(也就是一个普通的SELECT语句)时,InnoDB会根据这个查询给此事务分配一个时间点。若其余事务在此时间点以后删除了一行并提交,那么此事务不会看到其余事务产生的影响(即,仍是会看到被删除的行)。插入和更新操做也同样。看以下实验
create table test_cr( a int, b int )ENGINE=InnoDB DEFAULT CHARSET=utf8 mysql> select @@tx_isolation; +-----------------+ | @@tx_isolation | +-----------------+ | REPEATABLE-READ | +-----------------+
实验结果以下图:
从图中能够看出,在REPEATABLE READ事务隔离级别下,session A的事务以第一次执行select语句的时间点生成了快照,以后的select查询都是使用的此次快照数据。针对session B中事务做出的更新操做,若变动在session A中第一次select操做以前被commit,则session A的第一次select语句能够看到session B中的变动,不然看不到session B中的变动。
参考: