虽然平时已经很少使用MySQL了,但是数据库作为基本技能仍然不能忘,最近在学习数据库隔离级别,在此写下个人理解以备复习。

大家都知道数据库事务ACID(原子性、一致性、隔离性和持久性)的四个特征,也知道数据库存在三种并发问题(脏读、不可重复读、幻读),以及针对性的四种隔离级别(读未提交、读已提交、可重复读、序列化)。

解决与否 脏读 不可重复读 幻读
读未提交 Yes Yes Yes
读已提交 No Yes Yes
可重复读 No No Yes
串行化 No No No

特别提醒一句,隔离级别作用在连接(或会话)级别。客户端每次连接数据库的时候,都要根据自己对一致性的需求程度合理设置自己的事务隔离级别。

那么问题来了,MySQL底层(下文均指InnoDB引擎)是采用何种技术来实现这四种隔离级别的呢?

读未提交

MySQL全表的数据存储在以主键为排序值的B+树索引中,叶子节点存储了相应主键的整行记录。需要指出的是,叶子节点的数据都是最新的数据,可能是事务提交后的一致状态,也可能是事务执行中的中间值(可能被回滚)。

当隔离级别设置为RU时:

  • 所有的读不加锁,读到的都是叶子节点上最新的值,性能最好。
  • 所有的写(更新、插入、删除)加行级排斥锁,不存在脏写的问题,写完就释放锁。

读已提交

当隔离级别是RC和RR时,就要谈到大名鼎鼎的MVCC(多版本控制) 技术。通过在每行加入若干隐藏的字段,它实现了不加锁的读操作,性能较好。

  • 先说RC级别的写操作,MySQL依然加行级排斥锁。事务开始时会往UNDO日志中写入当前的有效记录值,B+树叶子节点的隐藏列DATA_ROLL_PTR会存储指向该UNDO记录的指针。顺着行的DATA_ROLL_PTR的指针形成一个链表,记录该行数据的有效的历史记录。
  • 再说不加锁的读操作,如果叶子节点正被其他事务锁定,那么MySQL顺着叶子节点的DATA_ROLL_PTR指针找到上一个有效的历史记录即可。

可重复读

在事务开始的时候,除了正常往UNDO日志中写回滚的数据外,会创建一个ReadView,记录了当前活跃的其他事务的ID,其中最小值为Tmin,最大值为Tmax。

当执行SELECT操作时,MySQL顺着行记录的DATA_ROLL_PTR指针查找符合条件的历史版本。这里就用到了另一个隐藏列DATA_TRX_ID,其中存储的是更新该记录的事务ID(事务ID是全局递增且唯一的)。如果DELETE_BIT为1,则代表ID为DATA_TRX_ID的事务对当前行执行了删除。

扫描历史版本串成的链表的过滤条件是:

  1. 如果当前记录的DATA_TRX_ID小于Tmin(之前存在的数据),那么由DELETE_BIT决定是否可见;否则,转2。
  2. 如果当前记录的DATA_TRX_ID小于Tmax,且不在活跃的事务ID集合中,那么由DELETE_BIT决定是否可见视为可见;否则,转3。
  3. 否则视为不可见,顺着DATA_ROLL_PTR进入上一个历史版本,或因为到头而结束回溯。

因为插入的数据版本号要么在活跃事务ID集合内、要么小于当前事务ID,所以MVCC机制同时解决了幻读问题。

需要指出的是,以上三个隔离级别中的读均为普通的SELECT。如果用的是SELECT ... LOCK IN SHARE MODE或SELCT ... FOR UPDATE,均属于当前读。即加读锁或写锁,读叶子节点最新值。如果更早的事务改了行值,依然会存在不可重复读的情况;如果前后两次读均为当前读,则不会如此(因为第一次读加锁了)。

在RR级别下,如果WHERE的条件列上有唯一索引,那么MySQL只加行级锁;如果是普通索引,会加间隙锁来防止幻读;如果没有索引,就会首先锁表的所有记录、再释放不符合条件的行的锁,因此会大大降低并发写的能力。

串行化

读写均加表级的读写锁即可,直接读主键索引B+树的叶子节点的最新数据。该级别下,数据一致性很强,但是并发写的能力非常差。

MySQL隔离级别的实现的更多相关文章

  1. mysql隔离级别的测试

    mysql提供四种隔离级别,以下分别对四种隔离级别进行测试,更加直观清晰的了解.具体的隔离级别以及其他相关介绍见https://www.cnblogs.com/eric-fang/p/11052304 ...

  2. mysql隔离级别的设置和检索

    001.设置方式: 001.在/etc/my.cnf配置文件中设置,这个格式一定要记清楚呀! transaction-isolation=READ-COMMITTED 这里要写在“-”号不是“_&qu ...

  3. [转帖]MySQL的又一神器-锁,MySQL面试必备

    MySQL的又一神器-锁,MySQL面试必备 https://segmentfault.com/a/1190000020762791 lock 低一级的是 latch   原文链接:blog.ouya ...

  4. 一文彻底读懂MySQL事务的四大隔离级别

    前言 之前分析一个死锁问题,发现自己对数据库隔离级别理解还不够清楚,所以趁着这几天假期,整理一下MySQL事务的四大隔离级别相关知识,希望对大家有帮助~ 事务 什么是事务? 事务,由一个有限的数据库操 ...

  5. MySQL 面试必备:又一神器“锁”,不会的在面试都挂了

    1 什么是锁 1.1 锁的概述 在生活中锁的例子多的不能再多了,从古老的简单的门锁,到密码锁,再到现在的指纹解锁,人脸识别锁,这都是锁的鲜明的例子,所以,我们理解锁应该是非常简单的. 再到MySQL中 ...

  6. 事务的隔离级别与MVCC

    提到数据库,你多半会联想到事务,进而还可能想起曾经背得滚瓜乱熟的ACID,不知道你有没有想过这个问题,事务有原子性.隔离性.一致性和持久性四大特性,为什么偏偏给隔离性设置了级别? 一切还得从事务说起. ...

  7. MySQL 四种事务隔离级的说明

    很早之前写的文章,重新回顾和学习下: 按照SQL:1992 事务隔离级别,InnoDB默认是可重复读的(REPEATABLE READ).MySQL/InnoDB 提供SQL标准所描述的所有四个事务隔 ...

  8. MySQL事务隔离级别的实现原理

    回顾 在MySQL的众多存储引擎中,只有InnoDB支持事务,所有这里说的事务隔离级别指的是InnoDB下的事务隔离级别. 读未提交:一个事务可以读取到另一个事务未提交的修改.这会带来脏读.幻读.不可 ...

  9. Spring事务管理与数据库隔离级别的关系(Spring+mysql)

    之前写过一篇文章<数据库隔离级别(mysql+Spring)与性能分析 >,里面很多问题写的不是很专业,也不是很有逻辑性,现在重新整理一下,希望对大家有帮助. 这部分通过两天时间反复的 ...

随机推荐

  1. 精尽Spring Boot源码分析 - 内嵌Tomcat容器的实现

    该系列文章是笔者在学习 Spring Boot 过程中总结下来的,里面涉及到相关源码,可能对读者不太友好,请结合我的源码注释 Spring Boot 源码分析 GitHub 地址 进行阅读 Sprin ...

  2. PUN丨实用API

    原文地址:PUN丨实用API 当前房间人数 int num = PhotonNetwork.CurrentRoom.PlayerCount; 当前脚本是否属于当前玩家 //需继承MonoBehavio ...

  3. centos使用yum安装docker

    1.先决条件 要安装 Docker 引擎,您需要 CentOS 7 或 8 的维护版本.不支持或测试存档版本. 该centos-extras库必须启用.默认情况下启用此存储库,但如果您已禁用它,则需要 ...

  4. IE浏览器 AjaxForm文件上传错误:Stream ended unexpectedly

    错误日志: 1 org.springframework.web.multipart.MultipartException: Failed to parse multipart servlet requ ...

  5. 资源:docker-compose下载路径

    docker-compose下载路径: compose所有版本:https://github.com/docker/compose/releases

  6. php混淆加密解密实战

    在查看别人的php源码的时候,我们经常会看到加密后的php代码.那么php加密原理是什么呢?怎么解密呢? 混淆加密 我们从百度随便搜索一个加密网站,例如:http://dezend.qiling.or ...

  7. java封装继承以及多态(含代码)

    封装 该露的露,该藏的藏 我们常需设计要追求,"高内聚,低耦合".高内聚就是类的内部数据操作细节自己完成.不允许外部干涉:低耦合:仅暴漏少量的方法给外部使用. 封装(数据的隐藏) ...

  8. linux中如何添加用户并赋予root权限详解

    #adduser username 修改 /etc/sudoers 文件,找到下面一行,在root下面添加一行,如下所示: ## Allow root to run any commands anyw ...

  9. 备战-Java 基础

    备战-Java 基础 仰天大笑出门去,我辈岂是蓬蒿人. 简介:备战-Java 基础. 一.基本数据类型 1.Java基本数据类型 基本数据类型有8种:byte.short.int.long.float ...

  10. 干掉 Postman?测试接口直接生成API文档,这个工具贼好用

    大家好,我是小富~ 前几天粉丝群有小伙伴问,有啥好用的API文档工具推荐,无意间发现了一款工具,这里马不停蹄的来给大家分享一下. ShowDoc一个非常适合团队的在线API文档工具,也支持用docke ...