前言

  • 数据库的事务特性
  • 数据并发读写时遇到的一致性问题
  • mysql事务的隔离级别
  • MVCC的实现原理
  • 锁和隔离级别

关注公众号,一起交流,微信搜一搜: 潜行前行

1 数据库的事务特性

  • 原子性:同一个事务里的操作是一个不可分割的,里面的 sql 要么一起执行,要不执行,是原子性
  • 隔离性:数据库系统提供一定的隔离机制,保证事务在不受外部并发操作影响的“独立”环境执行。这意味着事务处理过程中的中间状态对外部是不可见的
  • 一致性:在事务开始和完成时,数据约束都必须保持一致状态
  • 持久性:事务完成之后,它对于数据的修改是永久性的,即使出现系统崩溃也能够保持持久

2 数据并发读写时遇到的一致性问题

  • 脏读(针对未提交)

    • 两个事务同时进行,事务A修改了数据D,且事务A未提交,而事务B却可以读取到未提交的数据D,称之为脏读
  • 脏写
    • 两个事务同时尝试去更新某一条数据记录时,当事务A更新时,事务A还没提交,事务B就也过来进行更新,覆盖了事务 A 提交的更新数据,这就是脏写。一般要加锁解决
  • 不可重复读(针对已提交的 update)
    • 针对的是已经提交的事务修改的值,同时进行的其他事务给读取到了,事务内多次查询,多次读到的是别的已经提交的事务修改过的值,这就导致不可重复读
  • 幻读(针对已提交的 insert)
    • 事务读取到事务开始之后的插入数据,例如select * from table_user where id between 1 and 10,这条sql本应查出 1~9 的数据,id=10 此时不存在,之后其他事务再插入了一条 id=10 的记录。然后当前事务再次查询则会查出 10 条记录。这就是幻读
    • 和不可重复读的区别是,不可重复读的问题是读取最新的修改,幻读是读取到最新的插入数据

3 mysql事务的隔离级别

  • 读未提交(READ UNCOMITTED,RU):对应脏读,可以读取到最新未提交的修改
  • 读已提交(READ COMMITTED,RC):一个事务能读取另一个事务已经提交的修改。其避免了脏读,但仍然存在不可重复读和幻读问题
  • 可重复读(REPEATABLE READ,RR):同一个事务中多次读取相同的数据返回的结果是一样的。其避免了脏读和不可重复读问题,但幻读依然存在
  • 串行化读(SERIALIZABLE):事务串行执行。避免了以上所有问题

4 MVCC 的实现原理

MVCC 全称Multi-Version Concurrency Control,其好处是读不加锁,读写不冲突,并发性能好

MVCC 的 undo log 版本链

  • InnoDB中每行数据都有隐藏列,隐藏列中包含了本行数据的事务ID trx_id、指向 undo log 的 roll_pointer 指针

  • 基于undo log的版本链:前面说到每行数据的隐藏列中包含了指向 undo log 的指针 roll_pointer,而每条undo log 也会指向更早版本的undo log,从而形成一条版本链

readView

对于使用READ COMMITTED和REPEATABLE READ隔离级别的事务来说,都必须保证读到已提交事务修改过的记录,也就是说假如另一个事务修改了记录但尚未提交,是不能读取最新版本的记录的,其核心问题:需要判断 MVCC 版本链中的哪个版本是当前事务可见的。innodb 的解决方案 readView,readView 包含4个比较重要的属性

  • m_ids:在生成ReadView时,当前系统中活跃的读写事务 id 列表
  • min_trx_id:表示在生成ReadView时,当前系统中活跃的读写事务中最小的事务id,也就是m_ids中的最小值
  • max_trx_id:表示生成ReadView时系统中应该分配给下一个事务的 id 值
  • creator_trx_id:对应生成该ReadView 事务的id
readView 的访问步骤
  • 如果被访问版本的trx_id属性值与ReadView中的creator_trx_id值相同,表示当前事务在访问它自己修改过的记录,该版本可以被当前事务访问。
  • 如果被访问版本的trx_id属性值小于ReadView中的min_trx_id值,表明生成该版本的事务在当前事务生成ReadView前已经提交,所以该版本可以被当前事务访问。
  • 如果被访问版本的trx_id属性值在ReadView的min_trx_id和max_trx_id之间,那就需要判断一下trx_id属性值是不是在m_ids列表中,如果在,说明创建ReadView时生成该版本的事务还是活跃的,该版本不可以被访问;如果不在,说明创建ReadView时生成该版本的事务已经被提交,该版本可以被访问
  • 如果被访问版本的trx_id属性值大于或等于ReadView中的max_trx_id值,表明生成该版本的事务在当前事务生成ReadView后才开启,该版本不可被当前事务访问。反之可见
  • 如果某个版本的数据对当前事务不可见的话,那就顺着版本链找到下一个版本的数据(undo log)。如果最后一个版本都不可见的话,那么就意味着该条记录对该事务完全不可见

读已提交和可重复读利用 ReadView 实现

  • 快照读:读取的是快照版本,也就是历史版本 readView 里的数据 ,普通的 SELECT 就是快照读
  • 当前读:读取的是最新版本,UPDATE、DELETE、INSERT、SELECT ... LOCK IN SHARE MODE、SELECT ... FOR UPDATE 是当前读,需要加锁
  • READ UNCOMMITTED:直接读取记录的最新版本就好
  • READ COMMITTED:每次读取数据前都生成一个ReadView
    • 针对当前读,RC 隔离级别保证对读取到的记录加锁 (记录锁),存在幻读现象
  • REPEATABLE READ:在第一次读取数据时生成一个ReadView
    • 针对当前读,RR 隔离级别保证对读取到的记录加锁 (记录锁),同时保证对读取的范围加锁,新的满足查询条件的记录不能够插入 (间隙锁),不存在幻读现象
    • RR 从严格意义上并没解决幻读。如果事务一开始先 update 一条看不见的数据(前面没有当前读操作),再查询,则会多查出这条记录,此时也是发生了幻读

5 锁和隔离级别

  • RC、RR、SERIALIZABLE 级别的隔离,当前读都会需要借助锁实现
  • MVCC 能实现多数情况避免幻读,但不能完全避免幻读的发生
  • RR 隔离级别需要先 select ... for update 加锁进行当前读操作,才能防止幻读
  • 对于SERIALIZABLE隔离级别的事务来说,InnoDB规定使用加锁的方式来访问记录

欢迎指正文中错误

参考文章

数据库篇:mysql事务原理之MVCC视图+锁的更多相关文章

  1. mysql事务原理及MVCC

    mysql事务原理及MVCC 事务是数据库最为重要的机制之一,凡是使用过数据库的人,都了解数据库的事务机制,也对ACID四个 基本特性如数家珍.但是聊起事务或者ACID的底层实现原理,往往言之不详,不 ...

  2. MySQL事务、并发问题、锁机制

    MySQL事务,并发问题,锁机制 1.什么是事务 事务是一条或多条数据库操作语句的组合,具备ACID,4个特点. 原子性:要不全部成功,要不全部撤销 隔离性:事务之间相互独立,互不干扰 一致性:数据库 ...

  3. java架构之路-(mysql底层原理)Mysql事务隔离与MVCC

    上几篇博客我们大致讲了一下mysql的底层结构,什么B+tree,什么Hash需要回行啊,再就是讲了mysql优化的explain,这次我们来说说mysql的锁. mysql锁 锁从性能上分为乐观锁( ...

  4. MySQL事务原理浅析

    前言​ 因为自己对数据的可靠性,可用性方面特别感兴趣,所以在MySQL事务方面看了很多资料,也看了很多博客,所以想到自己也写一篇博客整理整理自己所学内容,尽量用自己的语言解释得通俗易懂. 事务经典场景 ...

  5. 详解MySQL事务原理

    老刘是即将找工作的研究生,自学大数据开发,一路走来,感慨颇深,网上大数据的资料良莠不齐,于是想写一份详细的大数据开发指南.这份指南把大数据的[基础知识][框架分析][源码理解]都用自己的话描述出来,让 ...

  6. 【Spring】看了这篇Spring事务原理,我才知道我对Spring事务的误解有多深!

    写在前面 有很多小伙伴们留言说,冰河,你能不能写一篇关于Spring事务的文章呢?我:可以啊,安排上了!那还等什么呢?走起啊!! 事务的基本原理 Spring事务的本质其实就是数据库对事务的支持,没有 ...

  7. mysql事务原理以及锁

    一.Innodb事务原理 1.什么是事务 a.事务(Transaction)是数据库区别于文件系统的重要特性之一,事务会把数据库从一种一致性状态转换为另一种一致性状态. b.在数据库提交时,可以确保要 ...

  8. Mysql事务原理介绍

    事务 一个事务会涉及到大量的cpu计算和IO操作,这些操作被打包成一个执行单元,要么同时都完成,要么同时都不完成. 事务是一组原子性的sql命令或者说是一个独立的工作单元,如果数据库引擎能够成功的对数 ...

  9. Mysql事务原理

    一.什么是事务 事务:是数据库操作的最小工作单元,是作为单个逻辑工作单元执行的一系列操作:这些操作作为一个整体一起向系统提交,要么都执行.要么都不执行:事务是一组不可再分割的操作集合(工作逻辑单元): ...

随机推荐

  1. Java入土---基本DOS命令

    基本DOS命令 打开cmd方式 开始+系统+命令提示符 win+R,输入cmd 在任意文件夹下,按住shift + 右键,打开命令行窗口 资源管理器里打开 常用DOS命令 盘符切换 E: dir命令查 ...

  2. 理解并手写 bind() 函数

    有了对call().apply()的前提分析,相信bind()我们也可以手到擒来. 参考前两篇:'对call()函数的分析' 和 '对apply()函数的分析',我们可以先得到以下代码: Functi ...

  3. 腾讯2021LIGHT公益创新挑战赛赛题分析

    前些日子老师让我们报名了LIGHT挑战赛,之后又简单的进行了分析,今天我总结复盘一下,一是为了捋一下自己选题的思路,二是以后遇见类似的项目,更容易找到方向或者触类旁通. 赛题介绍 赛题一:安全教育/保 ...

  4. IIS将应用程序池配置为在计划时间执行回收 (IIS 7)

    将应用程序池配置为在计划时间执行回收 您可以通过以下方法执行此过程:使用用户界面 (UI).在命令行窗口中运行 Appcmd.exe 命令.直接编辑配置文件或编写 WMI 脚本. 如下只介绍用户界面U ...

  5. Pytorch自动混合精度(AMP)介绍与使用

    背景: pytorch从1.6版本开始,已经内置了torch.cuda.amp,采用自动混合精度训练就不需要加载第三方NVIDIA的apex库了.本文主要从三个方面来介绍AMP: 一.什么是AMP? ...

  6. JAVA 用命令提示符执行java找不到或者无法加载主类

    使用cmd编译执行java文件时候,报错---找不到或者无法加载主类如下图 把红色部分去掉,再次编译执行如下解决问题 ,执行成功!!!!!! 2.当我们在eclipes中执行运行的时候 ggggggg ...

  7. zookeeper的通知机制

    一.znode Zookeeper维护一个类似文件系统的数据结构.简单来说,有点类似windows中注册表的结构,有名称,有树节点,有Key(键)/Value(值)对的关系,可以看做一个树形结构的数据 ...

  8. 什么是springboot?为什么要用springboot?

    一.什么是springboot? Springboot是spring发展到一定程度的产物,但并不是spring的替代品,springboot是为了让程序员更好的使用spring.Spring随着发展逐 ...

  9. Java连接ArtemisMQ,出现Timed out waiting to receive cluster topology. Group:null异常

    完整异常内容:org.springframework.jms.UncategorizedJmsException: Uncategorized exception occurred during JM ...

  10. consumer提交offset原理

    1 数据结构 消费者的消费状态是保存在SubscriptionState类中的,而SubscriptionState有个重要的属性那就是assignment保存了消费者消费的partition及其pa ...