可重复读隔离级别,不允许存在幻读,该隔离级别之所以能够有效防止幻读现象的出现,是因为可重复读这个隔离级别有用到GAP锁(间隙锁)。下面我们以解析SQL语句为切入点,来解释个中原因。

  前提条件:①数据库的存储引擎为InnoDB; ②数据库的隔离级别为“可重复读”。

  SQL:DELETE FROM user WHERE id = 10;

  (1)当id是聚簇索引或唯一索引时:

    此时是没有使用到GAP锁的,但是也保证了幻读现象的出现。

    原因:如果id是主键,那么主键必然是“唯一且不为空”的;如果id是唯一索引,那么也保证了数据的唯一性。一个等值查询,最多只能返回一条记录,而且新的相同取值的记录,一定不会在新插入进来,因此也就避免了GAP锁的使用。

  (2)当id是非唯一索引时:

    此时就会用到GAP锁,此时的加锁行为如下图所示:

  

    GAP锁锁住的位置,并非记录本身,而是两条记录之间的GAP。    

    没有幻读:就是同一个事务中,连续做两次当前读 (例如:SELECT * FROM user WHERE id = 10 FOR UPDATE;),这两次当前读返回的是完全相同的记录 (记录数量一致,记录本身也一致),即第二次的当前读,不会比第一次返回更多的记录 (幻象)。

    如何保证两次当前读返回一致的记录,那就需要在第一次当前读与第二次当前读之间,其他的事务不会插入新的满足条件的记录并提交。为了实现这个功能,GAP锁应运而生。

    如图中所示,有哪些位置可以插入新的满足条件的项 (id = 10),考虑到B+树索引的有序性,满足条件的项一定是连续存放的。记录[6,c]之前,不会插入id=10的记录;[6,c]与[10,b]间可以插入[10, a]、[10,aa]等,[10,b]与[10,d]间,可以插入新的[10,bb],[10,c]等;[10,d]与[11,f]间可以插入满足条件的[10,e],[10,z]等;而[11,f]之后也不会插入满足条件的记录。因此,为了保证[6,c]与[10,b]间,[10,b]与[10,d]间,[10,d]与[11,f]不会插入新的满足条件的记录,MySQL选择了用GAP锁,将这三个GAP给锁起来。

    Insert操作,如insert [10,aa],首先会定位到[6,c]与[10,b]间,然后在插入前,会检查这个GAP是否已经被锁上,如果被锁上,则Insert不能插入记录。因此,通过第一遍的当前读,不仅将满足条件的记录锁上 (X锁),同时还是增加3把GAP锁,将可能插入满足条件记录的3个GAP给锁上,保证后续的Insert不能插入新的id=10的记录,也就杜绝了同一事务的第二次当前读,出现幻象的情况。

    结论:可重复读隔离级别下,id列上有一个非唯一索引,对应SQL:DELETE FROM user WHERE id = 10;首先,通过id索引定位到第一条满足查询条件的记录,加记录上的X锁,加GAP上的GAP锁,然后加主键聚簇索引上的记录X锁,然后返回;然后读取下一条,重复进行。直至进行到第一条不满足条件的记录[11,f],此时,不需要加记录X锁,但是仍旧需要加GAP锁,最后返回结束。

 

参考博客:http://hedengcheng.com/?p=771#_Toc374698322【作者:何登成    原文:MySQL 加锁处理分析】

MySQL数据库的隔离级别之可重复读为什么能够有效防止幻读现象的出现的更多相关文章

  1. Mysql数据库的隔离级别

    Mysql数据库的隔离级别有四种 1.read umcommitted   读未提交(当前事务可以读取其他事务没提交的数据,会读取到脏数据) 2.read committed 读已提交(当前事务不能读 ...

  2. MySQL - 数据库的隔离级别

    MySQL - 数据库的隔离级别 隔离级别 脏读(Dirty Read) 不可重复读(NonRepeatable Read) 幻读(Phantom Read) 未提交读(Read uncommitte ...

  3. Mysql数据库事务隔离级别

    事务(transaction)是数据库管理系统的执行单位,可以是一个数据库操作(如Select操作)或者是一组操作序列.事务ACID属性,即原子性(Atomicity).一致性(Consistency ...

  4. mysql事务之一:MySQL数据库事务隔离级别(Transaction Isolation Level)及锁的实现原理

    一.数据库隔离级别 数据库隔离级别有四种,应用<高性能mysql>一书中的说明: 然后说说修改事务隔离级别的方法: 1.全局修改,修改mysql.ini配置文件,在最后加上 1 #可选参数 ...

  5. 1.设置和验证MySQL数据库的隔离级别

    登录数据库 mysql -u root - p 新建用户,各启动一个事物,用于同时操作数据库表中数据 create user tom identified by 'tom'; 然后同时再用该用户启动M ...

  6. mysql数据库——事务隔离级别

    四种隔离级别: 一:READ UNCOMMITTED(未提交读) 事务可以读取其他事务未提交的数据,称为脏读 二:READ COMMITTED(提交读) 一个事务开始时,只能"看见" ...

  7. MySQL数据库事务隔离级别(Transaction Isolation Level)

    转自: http://www.cnblogs.com/zemliu/archive/2012/06/17/2552301.html  数据库隔离级别有四种,应用<高性能mysql>一书中的 ...

  8. [转]MySQL 数据库事务隔离级别

    然后说说修改事务隔离级别的方法: 1. 全局修改,修改 mysql.ini 配置文件,在最后加上 1 #可选参数有:READ-UNCOMMITTED, READ-COMMITTED, REPEATAB ...

  9. Java -- JDBC 事务处理, 事务的隔离级别 脏读 不可重复读 等...

    1. 事务指逻辑上的一组操作,组成这组操作的各个单元,要不全部成功,要不全部不成功. 数据库开启事务命令 •start transaction 开启事务 •Rollback  回滚事务 •Commit ...

随机推荐

  1. change grayscale to pseudo colouring using colormap in Matlab

    change grayscale to pseudo colouring using colormap in Matlab In matlab you can view a grayscale ima ...

  2. Windows 10 Framework 3.5 _x64 离线安装包 最新安装版

    原文:http://www.jb51.net/softs/325481.html Windows 10 Framework 3.5 离线安装包,适用于 Win10 和 Server 2016 离线安装 ...

  3. leetcode Ch5-Linked List

    一. 1. Remove Duplicates from Sorted List II class Solution { public: ListNode* deleteDuplicates(List ...

  4. centos7 docker 使用pipework 做虚拟机

    网卡配置文件 及 bridge的静态配置 centos7 Bridge配置 [root@mon-1 ~]# cd  /etc/sysconfig/network-scripts/ [root@mon- ...

  5. Objective-C与JavaScript交互的那些事

    http://www.cocoachina.com/ios/20160127/15105.html 最近公司的运营瞎搞了个活动,其活动要服务端提供数据支持,web前端在微信公众账号内作为主要的运营阵地 ...

  6. TensorFlow函数(三)tf.variable_scope() 和 tf.name_scope()

    tf.name_scope() 此函数作用是共享变量.在一个作用域scope内共享一些变量,简单来说,就是给变量名前面加个变量空间名,只限于tf.Variable()的变量 tf.variable_s ...

  7. 34、springboot的热部署

    热部署 在开发中我们修改一个Java文件后想看到效果不得不重启应用,这导致大量时间花费, 我们希望不重启应用的情况下,程序可以自动部署(热部署).有以下四种情况,如何能实现热部署. 1.模板引擎 在S ...

  8. js中时间的操作

    var myDate = new Date();myDate.getYear();        //获取当前年份(2位)myDate.getFullYear();    //获取完整的年份(4位,1 ...

  9. Hadoop 解除 NameNode is in safe mode

    运行Hadoop程序时,有时候会报以下错误: org.apache.hadoop.dfs.SafeModeException: Cannot delete /user/hadoop/input. Na ...

  10. Python自动化之Django中间件

    django中间件 Django请求生命周期 中间件中可以定义方法,分别是 process_request(self,request) process_view(self, request, call ...