MySQL知识点回顾:锁问题(二)不可重复读

  不可重复读是指在一个事务内多次读取同一数据集合。在这个事务还没有结束时,另外一个事务也访问该同一数据集合,并做了一些DML操作。因此,在第一个事务中的两次读数据之间,由于第二个事务的修改,那么第一个事务两次读到的数据可能是不一样的。这样就发生了在一个事务内两次读到的数据是不一样的情况,这种情况称为不
可重复读。
  不可重复读和脏读的区别是:脏读是读到未提交的数据,而不可重复读读到的却是已经提交的数据,但是其违反了数据库事务一致性的要求。可以通过下面一个例子来观察不可重复读的情况。

以下例子是在READ COMMITTED隔离级别下进行的
首先设置当前两个会话的事务隔离级别为READ COMMITTED

set session transaction isolation level read committed;
时间点会话A会话B
时间点1begin;
时间点2begin;
时间点3select * from t;
时间点4insert into t values(2,2);
时间点5select * from t;
时间点6commit;
时间点7select * from t;
时间点7commit;

在这里插入图片描述

分析如下:
  在会话A中开始一个事务,第一次进行查询读取到的数据只有三条。
  然后在会话B中开始了另一个事务,插入了一条为id=2,code=2的数据,在没有进行提交之前,对会话A进行了一次读取,读取到的数据也是只有三条,证明没有发生脏读的现象。但是当会话B的事务提交了之后,在会话A中再次进行读取的时候,可以发现数据有四条了。

总结:
  一般来说,不可重复读的问题是可以接受的,因为其读到的是已经提交的数据,本身并不会带来很大的问题。因此,很多数据库厂商(如Oracle、Microsoft SQL Server)将其数据库事务的默认隔离级别设置为READ COMMITTED,在这种隔离级别下允许不可重复读的现象。
  在InnoDB存储引擎中,通过使用Next-Key Lock算法来避免不可重复读的问题。在MySQL官方文档中将不可重复读的问题定义为Phantom Problem,即幻像问题。在Next-Key Lock算法下,对于索引的扫描,不仅是锁住扫描到的索引,而且还锁住这些索引覆盖的范围(gp)。因此在这个范围内的插人都是不允许的。这样就避免了另外的事务在这个范围内插入数据导致的不可重复读的问题。因此,nnoDB存储引擎的默认事务隔离级别是READ REPEATABLE,采用Next-Key Lock算法,避免了不可重复读的现象。

特别鸣谢:MYSQL技术内幕INNODB存储引擎【机械工业出版社】

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值