事务及事务隔离级别

innodb存储引擎支持事务,myisam不支持事务

事务内的操作要么全部成功,要么全部失败,中途有失败则回滚

事务的ACID:原子性,一致性,隔离性,持久性

事务隔离级别需要解决的问题:

  • 脏读:读到其他事务未提交的事务

  • 不可重复读:同一事务内,不同时刻读到的同一批数据可能不一样

  • 幻读:对于插入来说的,事务A按照一定条件进行数据读取,期间事务B插入了相同搜索条件的新数据,事务A再次按照原先条件进行读取时,发现事务B新插入的数据

事务隔离级别:

  • 读未提交

  • 读提交

  • 可重复读(默认隔离级别)

  • 串行化

从上至下隔离强度逐渐增强

读未提交:不加锁,连脏读问题都解决不了

读提交:解决了脏读,但是还有不可重复读的问题。因为可能某个事务查询期间,有另一个事务修改并提交了数据,则可能导致同一事务两次数据读到的不一样。

可重复读:事务不会读到其他事务对已有数据的修改,事务开始有什么数据,那么事务提交前的任意时刻,数据都是一样的。但是,对于事务新插入的数据是可以读到的,这也就是幻读的问题。但是需要强调的是,MySQL的可重复读其实解决了幻读的问题。

串行化:问题都解决了,但是将事务的执行变为了顺序查询,相当于当线程。

MySQL如何实现事务隔离级别?

读未提交:不加锁,可以理解为没有隔离。

串行化:读的时候加共享锁,写的时候加排他锁。

剩下的两个既要允许一定的并发,又要解决一些问题,因此比较复杂。

MVCC

MySQL采用MVCC(多版本并发控制)的方式,实现读提交和可重复读

对于一个快照来说,能读到哪些基于以下规则:

  1. 当前事务内的更新,可以读到

  2. 版本未提交,不能读到

  3. 版本已提交,但是在快照创建后提交的,不能读到。

  4. 版本已提交,且是在快照创建前提交的,可以读到。

对于快照读(select)

对于读提交,每次进行快照读时都会生成最新的Read View

对于可重复读,只有事务开始的第一个快照读会创建Read View

对于当前读(update,insert,delete)

行锁加间隙锁来解决,这个合并的锁叫做Next-Key锁

在修改的记录两边的区间加上间隙锁。

这里需要注意一个问题,加锁的过程要分为有索引和无索引两种情况,有索引时,直接通过索引找到数据行,直接加锁。对于没有索引的,会为这张表所有行加上锁,不满足条件的释放锁,留下满足条件的,会极大影响性能。

漏洞?:默认隔离级别(可重复读)

  1. 事务A select

  2. 事务B insert

  3. 事务B commit

  4. 事务A select(与第一次select的结果一样)

  5. 事务A update 所有行

  6. 事务A select(会发现多出了事务B insert 的行)

这算出现了幻读吗?

所以说MVCC并不能完美解决RR下的幻读问题??

一旦事务A的修改操作覆盖到了其他事务插入的“幻行”,那么在下次select的时候,也会把这行数据一起查出来

要解释这个现象,需要深入理解MVCC

隐藏字段

  1. DB_TRX_ID(6字节):表示最近一次对本记录行作修改(insert | update)的事务ID。至于delete操作,InnoDB认为是一个update操作,不过会更新一个另外的删除位,将行表示为deleted。并非真正删除。

  1. DB_ROLL_PTR(7字节):回滚指针,指向当前记录行的undo log信息

  2. DB_ROW_ID(6字节):随着新行插入而单调递增的行ID。理解:当表没有主键或唯一非空索引时,innodb就会使用这个行ID自动产生聚簇索引。如果表有主键或唯一非空索引,聚簇索引就不会包含这个行ID了。

Read View结构

low_limit_id:目前出现过的最大的事务ID+1,即下一个将被分配的事务ID

up_limit_id:活跃事务列表trx_ids中最小的事务ID,如果trx_ids为空,则up_limit_id 为 low_limit_id

trx_ids:Read View创建时其他未提交的活跃事务ID列表。

creator_trx_id:当前创建事务的ID,是一个递增的编号

比较算法

db_trx_id < up_limit_id || db_trx_id == creator_trx_id(显示)

如果数据事务ID小于read view中的最小活跃事务ID,则可以肯定该数据是在当前事务启之前就已经存在了的,所以可以显示。

或者数据的事务ID等于creator_trx_id ,那么说明这个数据就是当前事务自己生成的,自己生成的数据自己当然能看见,所以这种情况下此数据也是可以显示的。

db_trx_id >= low_limit_id(不显示)

如果数据事务ID大于read view 中的当前系统的最大事务ID,则说明该数据是在当前read view 创建之后才产生的,所以数据不显示。如果小于则进入下一个判断

db_trx_id是否在活跃事务(trx_ids)中

不存在:则说明read view产生的时候事务已经commit了,这种情况数据则可以显示。

已存在:则代表我Read View生成时刻,你这个事务还在活跃,还没有Commit,你修改的数据,我当前事务也是看不见的。

实际例子

对应的事务10003的实际运行的三次select(原始数据id=1,age=19)

那么这个叫出现了幻读吗?

快照读和当前读混用造成的异常,不能算是出现了幻读

当前读的效果就是要读取最新版本,实际上是把隔离级别从 repeatable-read 降级到了 read-committed,所以快照读和当前读混用不算幻读。

我们是不是得说这个例子说明了 repeatable-read 允许“不可重复读异常现象”?显然不能。对于不可重复读异常,repeatable-read 隔离级别是明确不允许的。这就说明了当前读和快照读混用带来的异常不能称为幻读。

总结:

  1. MVCC能实现快照读的可重复读,不会出现不可重复读和幻读

  2. 间隙锁加行锁(或者说Next-Key锁),实现当前读的可重复读,也不会出现不可重复读和幻读

  3. 快照读和当前读混用造成的异常,不能算是出现了幻读

MySQL可重复读隔离级别能解决幻读吗?相关推荐

  1. MySQL可重复读隔离级别为何没有解决幻读(MVCC原理简介)

    MySQL可重复读隔离级别为何没有解决幻读(MVCC原理简介) 一.MCVV简介 二.可重复读隔离级别能解决幻读? 三.什么是当前读和快照读? 四.MVCC的实现原理 五.RC,RR级别下的InnoD ...

  2. Mysql可重复读隔离级别下如何解决幻读

    Mysql可重复读隔离级别下如何解决幻读 一些概念 具体加锁说明 使用主键索引进行等值查询 使用主键索引进行范围查询 使用二级索引进行等值查询 使用二级索引进行范围查询 一些概念 幻读:在一次事务中, ...

  3. MySQL 可重复读隔离级别,完全解决幻读了吗?

    我在上一篇文章中提到,MySQL InnoDB 引擎的默认隔离级别虽然是「可重复读」,但是它很大程度上避免幻读现象(并不是完全解决了),解决的方案有两种: 针对快照读(普通 select 语句),是通 ...

  4. 可重复读隔离级别如何解决脏读、不可重复读

    我们都知道可重复读隔离级别可以解决脏读.不可重复读.那么具体是如何解决的呢? 下面先通过实验来演示可重复读能够解决脏读.不可重复读问题,然后解释具体的原因. 环境搭建 1. 建立两个session连接 ...

  5. mysql脏读,幻读,不可重复读以及间隙所解决幻读

    1.数据脏读 事务a修改了某条数据,然后事务b读取了事务a修改的该条数据,然后事务a由于某些原因,事务a回滚了,这样事务b读到的数据就和回滚的数据不同了,这时事务b读取的数据就是脏数据.概况一句话就是 ...

  6. InnoDB在RR隔离级别下解决幻读问题

    表象:快照读(非阻塞读)-伪MVCC 内在:next-key锁(行锁+gap锁) 当前读和快照读 当前读:select-lock in share mode(共享锁),select-for updat ...

  7. MySQL 可重复读隔离级别与幻读

    在MySQL可重复读的隔离级别下,能很大程度上避免幻读,而不能完全避免. 场景复现 环境信息: MySQL版本:5.7.23-log 隔离级别:REPEATABLE-READ 测试数据: SET NA ...

  8. MySQL事务的四种隔离级别,mysql中的不可重复读和幻读的区别,Repeatable read可重复读隔离级别下怎么不存在幻读问题?

    1. 事务的隔离级别 1.1 read uncommited:读未提交.一个事务读到了另一个事务未提交的脏数据,称之为脏读. 1.2 read commited:读已提交.解决了脏读问题,但当前事务两 ...

  9. mysql幻读和不可重复读的区别_面试官:MySQL的可重复读级别能解决幻读吗

    Java面试笔试面经.Java技术每天学习一点 Java面试 关注不迷路 作者:宁愿. 来源:https://juejin.im/post/5c9040e95188252d92095a9e 引言 之前 ...

最新文章

  1. 一文详解相机标定算法原理
  2. 指定动态分区_重点解析!2021湖南中级职称评审动态趋势
  3. android progressbar 不显示_Android多线程技术选型最全指南(1)
  4. CTFshow 反序列化 web270
  5. boost::mp11::mp_same相关用法的测试程序
  6. python 类中定义列表_Python-从类定义中的列表理解访问类变量
  7. C++ 函数参数的默认值和占位参数
  8. 多线程设计模式 - Future模式
  9. 后台扫描工具 - 御剑(珍藏版)附下载
  10. BLUE引擎检查放入装备的名称全名脚本
  11. Unity序列化——Assets序列化
  12. 5G网络架构 — 接入网/传输网/核心网
  13. cmd安装pip以及第三方库的最简单的安装方法
  14. android 多张图片渐变切换控件
  15. 计算机第二课堂教学计划,第二课堂教学计划
  16. esp32 Flash分区与OTA功能简析
  17. muParser公式库使用简介( 转)
  18. OpenCms创建网站过程图解——献给OpenCms的初学者们
  19. 北京实时公交查询——Flutter 入坑实战
  20. sql函数DATEPART()与DATENAME()

热门文章

  1. C语言基础——1024我把函数献给你
  2. 关于技术人员创业的几点建议
  3. 微信小程序使用 iconfont 彩色图标(mini-program-iconfont-cli)
  4. win10子系统ubuntu18安装到其他盘
  5. 程序员需要具备的五个基本条件
  6. OpenCv-C++-小案例实战-切边(二)
  7. 用友iuap低代码开发驱动商业创新
  8. php 车牌号限号,不限行也不限号!还能送车牌?这种车你考虑吗?
  9. 计算机科学应用论文题目,比较好写的计算机科学与应用论文题目 计算机科学与应用论文题目怎么取...
  10. 快速打开电脑计算机的快捷键,电脑自带的计算器如何快速打开和快捷键的添加...