一致性非锁定读是指InnoDB存储引擎根据行多版本控制来读取当前执行数据库中的数据。
一、概念分析
当线程对数据库中的某行数据进行DELETE、UPDATE操作时,如果该行上面有排他锁(XLock)的存在,则该线程不会等待该锁的释放,而是读取该行的一个快照数据,来完成数据读取。之所以称之为非锁定读,是因为在线程读取数据时,不用等待数据行上锁的释放。
二、实际案例测试
准备工作:建立两个数据库连接Session,模仿并发访问数据库
建立Session A,在该会话中,我们开启一个事务,执行SELECT语句,查询到id = 3 的数据,不要提交事务,另外开启一个Session B会话连接:
在会话B中我们将id = 3 的数据更改为 id = 5,由于根据InnoDB存储引擎的特性,根据不同的事务隔离级别,我们读取到的值是不一样的,而此时,两个会话的事务都没有提交,我们在会话1中执行SELECT语句查询的结果应该是没有变化的。
当我们将会话B中的事务提交,也就是将数据库中的数据进行更改,我们来看看情况会变的咋样
因为快照数据是事务提交之前该行数据的版本,而此时数据库修改了一次,就生成了一个快照文件。而我们知道,在不同的事务隔离级别之下,我们会读取到不同的数据,所以,我们这是在会话A中,进行SELECT语句查询数据,由于InnoDB存储引擎默认的事务隔离级别是REPEATABLE READ,所以,先应该修改一下数据库的隔离级别
这时,在会话A中读取数据
当更改为REPEATABLE READ时,我们再来看看
我们会发现在隔离级别是READ COMMIT下,数据库一致性非锁定读读取到的是最新的一次快照数据,而在REPEATABLE READ事务隔离级别下,总是读取的是事务开始的行数据,也就是上面二者的数据为啥会有差异的原因。
一致性锁定读
在InnoDB存储引擎中,在默认事务隔离级别REPEATABLE READ下,SELECT操作使用一致性非锁定读,而在实际的开发过程中,开发者需要显示的对数据库进行加锁来保证逻辑一致性,对于我们的SELECT语句亦是如此。
InnoDB针对SELECT查询支持两种一致性锁定读
1、SELECT …… FOR UPDATE (X锁,排他锁)
2、SELECT …… LOCK IN SHARE MODE(S锁,共享锁)
需要注意一点的是,而这必须保证在同一个事务中,事务结束了,锁也就释放了,所以,在使用的过程中应该注意一下。