InnoDB的锁定读与一致性非锁定读

InnoDB的锁定读与一致性非锁定读

本文主要介绍InnoDB的:锁定读和一致性非锁定读html

锁定读(Locking Reads)

在一个事务中查询数据时,普通的SELECT语句不会对查询的数据进行加锁,其余事务仍能够对查询的数据执行更新和删除操做。所以,InnoDB提供了两种类型的锁定读来保证额外的安全性:mysql

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

SELECT ... LOCK IN SHARE MODE: 对读取的行添加S锁,其余事物能够对这些行添加S锁,若添加X锁,则会被阻塞。sql

SELECT ... FOR UPDATE: 会对查询的行及相关联的索引记录加X锁,其余事务请求的S锁或X锁都会被阻塞。数据库

当事务提交或回滚后,经过这两个语句添加的锁都会被释放。安全

注意:只有在自动提交被禁用时,SELECT FOR UPDATE才能够锁定行,若开启自动提交,则匹配的行不会被锁定。session

一致性非锁定读(Consistent Nonlocking Reads)

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事务隔离级别下,同一事务内的全部一致性读都会读取到该事务中第一个一致性读创建的快照。经过提交当前事务并发起一个新的查询,能够看获得新的快照。
  • 在READ COMMITTED事务隔离级别下,同一事务内的每一个一致性读老是读取本次一致性读创建的快照。(即,快照的时间点是基于本次一致性读的时间点,也就是最新的数据)

假设当前事务隔离级别为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隔离级别下,一致性非锁定读的实验

从图中能够看出,在REPEATABLE READ事务隔离级别下,session A的事务以第一次执行select语句的时间点生成了快照,以后的select查询都是使用的此次快照数据。针对session B中事务做出的更新操做,若变动在session A中第一次select操做以前被commit,则session A的第一次select语句能够看到session B中的变动,不然看不到session B中的变动。

参考:

相关文章
相关标签/搜索