【MySQL 数据宝典】【事务锁】- 002 事务控制的演进

一、事务处理思路

1.1 排队

排队处理是事务管理最简单的方法,就是完全顺序执行所有事务的数据库操作,不需要加锁,简单的说就是全局排队。序列化执行所有的事务单元,数据库某个时刻只处理一个事务操作,特点是强一致性,处理性能低。
image.png

1.2 排它锁

引入锁之后就可以支持并发处理事务,如果事务之间涉及到相同的数据项时,会使用排他锁,或叫互斥锁,先进入的事务独占数据项以后,其他事务被阻塞,等待前面的事务释放锁。
image.png

1.3 读写锁

读和写操作:读读、写写、读写、写读。
读写锁就是进一步细化锁的颗粒度,区分读操作和写操作,让读和读之间不加锁,这样下面的两个事务就可以同时被执行了。
image.png
读写锁,可以让读和读并行,而读和写、写和读、写和写这几种之间还是要加排他锁。

1.4 乐观锁

通过版本进行判断,MVCC 就是其中一种实现方式

二、 MVCC

2.1 基础概念

MVCC(Multi Version Concurrency Control)被称为多版本控制,是指在数据库中为了实现高并发的数据访问,对数据进行多版本处理,并通过事务的可见性来保证事务能看到自己应该看到的数据版本。
MVCC最大的好处是读不加锁,读写不冲突。在读多写少的系统应用中,读写不冲突是非常重要的,极大的提升系统的并发性能,这也是为什么现阶段几乎所有的关系型数据库都支持 MVCC 的原因,不过目前MVCC只在** Read Commited** 和 **Repeatable Read **两种隔离级别下工作。

2.2 Undo Log 多版本链

在前面我们介绍过,每条数据都有两个隐藏的字段,事务 Id (trx_id),回滚指针 (roll_pointer)

  • trx_id : 记录最近一次更新这条数据的事务 Id
  • roll_pointer : 指向之前生成的 undo log

生成流程

image.png
接着又有一个事务B (trx_id=58) 过来,对同一条数据进行修改,将值改为B,事务B的id是58,在更新之前会生成一个undo log来记录之前的值.然后会让roll_pointer指向这个实际的undo log回滚日志:
image.png
如果再有一个事务C (trx_id=69) 继续更新该条记录值为C,则会跟第二步的步骤一样
image.png
总结: 每一条数据都有多个版本,版本之间通过 undo log 链来进行连接
好处: 每个事务提交的时候一旦需要回滚操作,可以保证同一个事务只能读到比当前版本更早提交的值

2.3 Read View

核心解决问题: 需要判断一下版本链中的哪个版本是当前事务可见的
image.png
如上是一个 Read View 所存储的信息

  • m_ids :表示在生成 ReadView 时当前系统中活跃的读写事务的 事务id 列表。
  • min_trx_id :表示在生成 ReadView 时当前系统中活跃的读写事务中最小的 事务id ,也就是 m_ids 中的最 小值。
  • creator_trx_id :表示生成该 ReadView 的事务的 事务id 。
  • max_trx_id :表示生成 ReadView 时系统中应该分配给下一个事务的 id 值。

注意max_trx_id并不是m_ids中的最大值,事务id是递增分配的。比方说现在有id为1,2,3这三 个事务,之后id为3的事务提交了。那么一个新的读事务在生成ReadView时,m_ids就包括1和2,mi n_trx_id的值就是1,max_trx_id的值就是4。

我们前边说过,只有在对表中的记录做改动时(执行INSERT、DELETE、UPDATE这些语句时)才会 为事务分配事务id,否则在一个只读事务中的事务id值都默认为0。

核心流程

  1. 假设数据库有一行数据,很早就有事务操作过,事务id 是32. 此时两个事务并发过来执行了, 一个事务A (id=45),一个事务B (id=59). 事务A需要读取数据,而事务B需要更新数据,如下图:

image.png

如果不加任何限制,这里会出现脏读的情况,也就是一个事务可能会读到一个没有提交的值.

  1. 现在事务A直接开启一个ReadView,这个ReadView里的m_ids就包含了事务A和事务B的两个id,45和59,然后min_trx_id就是45,max_trx_id就是60. creator_trx_id就是45,是事务A自己。

image.png

  1. 此时事务A第一次查询这行数据,首先会判断一下当前这行数据的txr_id是否小于ReadView中的min_trx_id,此时发现txr_id=32,是小于ReadView里的min_trx_id就是45的,说明你事务开启之前,修改这行数据的事务已经提交了,所以此时可以查到这行数据,如下图所示:

image.png

  1. 接下来事务B开始操作该条数据,他把这行数据的值修改为了值B,然后将这行数据的txr_id设置为自己的id,也就是59,同时roll_pointer指向了修改之前生成的一个undo log,然后事务B提交,如下图所示

image.png

  1. 这时事务A再次执行了查询,但是却发现数据行里的txr_id=59
  • max_trx_id(60)>trxid (59) > mintrxid(45): 说明当前事务的数据是可能在自己同一时刻开启的
  • m_ids(45,59)包含了当前事务,说明就是同一时刻

所以当前记录无法查询
image.png

  1. 事务A根据roll_point顺着undo log版本链向下找,找到最近的一条undo log,trx_id是32。由于trx_id=32小于ReadView里的min_trx_id(45),说明这个undo log版本是在事务A开启之前就执行且提交的。因此,事务A可以查询最近的这个undo log里的值,这时undo log版本链的作用就体现出来了,它保存了一条快照链条,而事务A读取到的数据就是之前的快照数据。

image.png

Read View总结

  • 通过Read View判断记录的某个版本是否可见的方式总结:
    • trx_id = creator_trx_id
      如果被访问版本的trx_id,与readview中的creator_trx_id值相同,表明当前事务在访问自己修改过的记录,该版本可以被当前事务访问.
    • trx_id < min_trx_id
      如果被访问版本的trx_id,小于readview中的min_trx_id值,表明生成该版本的事务在当前事务生成readview前已经提交,该版本可以被当前事务访问.
    • trx_id >= max_trx_id
      如果被访问版本的trx_id,大于或等于readview中的max_trx_id值,表明生成该版本的事务在当前事务生成readview后才开启,该版本不可以被当前事务访问.
    • trx_id > min_trx_id && trx_id < max_trx_id
      如果被访问版本的trx_id,值在readview的min_trx_id和max_trx_id之间,就需要判断trx_id属性值是不是在m_ids列表中?
      • 在:说明创建readview时生成该版本的事务还是活跃的,该版本不可以被访问
    • 不在:说明创建readview时生成该版本的事务已经被提交,该版本可以被访问
  • 生成readview时机
    • RC隔离级别:每次读取数据前,都生成一个readview.
    • RR隔离级别:在第一次读取数据前,生成一个readview,之后read view不再更新.

2.4 MVCC 在 MySQL 中的具体实现

2.4.1 简介

MySQL中实现MVCC(多版本并发控制)的机制主要基于undo log多版本链和ReadView机制。下面是MySQL中MVCC的实现方式的详细说明:

2.4.2 数据表隐藏字段

MySQL为了实现MVCC,在每个表中添加了一些隐藏字段:

  • DATA_TRX_ID(6字节): 记录最新更新该行记录的事务ID,每个事务处理时会自动设置为当前事务ID。但值得注意的是,DATA_TRX_ID只有在事务提交之后才会更新。
  • DATA_ROLL_PTR(7字节): 一个rollback指针,指向当前行数据的上一个版本。通过这个指针将数据的多个版本连接在一起构成一个undo log版本链。
  • DB_ROW_ID(6字节): 隐含的自增ID,用来唯一标识每一行的字段。
  • DELETE BIT位: 标识当前记录是否被删除,实际上并不是真正的删除数据,而是一个标志。真正的删除操作是在事务提交的时候执行。

2.4.3 场景示例

查询 SELECT
  1. 在查询时,InnoDB只查找版本早于当前事务版本的数据行,即数据行的版本必须小于等于当前事务的版本。这确保当前事务读取的行都是事务之前已经存在的,或者是由当前事务创建或修改的行。
  2. 对于被删除的行,其删除操作的版本一定是未定义的或者大于当前事务的版本号,这意味着在当前事务开始之前,行没有被删除。只有符合以上两点,才会返回查询结果。
删除 DELETE
  • 删除操作会修改DATA_TRX_ID的值为当前执行删除操作的事务ID,并将DELETE BIT设置为True,表示被删除。
增加 INSERT
  • 新记录的DATA_TRX_ID会被设置为当前事务ID。
修改 UPDATE
  • 修改操作会使用排它锁锁定该行,以保证写操作的一致性。
  • 同时,会记录redo log,将更新之后的数据记录到redo log中,以便日后使用。
  • 也会记录undo log,将更新之前的数据记录到undo log中,以便回滚操作。

2.4.4 总结

通过undo log多版本链和ReadView机制的结合,MySQL实现了MVCC机制,确保了数据库在并发操作下的一致性和隔离性。

三、MVCC 读操作分类

在 MVCC 并发控制中,读操作可以分为两类: 快照读(Snapshot Read)与当前读 (Current Read)。

  • 快照读
    快照读是指读取数据时不是读取最新版本的数据,而是基于历史版本读取的一个快照信息(mysql读取undo log历史版本) ,快照读可以使普通的SELECT 读取数据时不用对表数据进行加锁,从而解决了因为对数据库表的加锁而导致的两个如下问题
    1. 解决了因加锁导致的修改数据时无法对数据读取问题.
    2. 解决了因加锁导致读取数据时无法对数据进行修改的问题.
  • 当前读
    当前读是读取的数据库最新的数据,当前读和快照读不同,因为要读取最新的数据而且要保证事务的隔离性,所以当前读是需要对数据进行加锁的
    • Update delete insert select ....lock in share mode
    • select for update 为当前读

MVCC已经实现了读读、读写、写读并发处理,如果想进一步解决写写冲突,可以采用下面两种方案:

  • 乐观锁
  • 悲观锁

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/10108.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Java刷题-基础篇

目录 题目1&#xff1a;打印1~100内奇数和、偶数和 题目2&#xff1a;计算5的阶乘 题目3&#xff1a;计算 1!2!3!4!5! 的和 题目4&#xff1a;找1~100之间即能被3整除&#xff0c;又能被5整除的数字&#xff0c;要求必须使用break/continue 题目5&#xff1a;实现猜数字小…

LeetCode 112. 路径总和 || LeetCode 113. 路径总和ii

LeetCode 112. 路径总和 1、题目 题目链接&#xff1a;112. 路径总和 给你二叉树的根节点 root 和一个表示目标和的整数 targetSum 。判断该树中是否存在 根节点到叶子节点 的路径&#xff0c;这条路径上所有节点值相加等于目标和 targetSum 。如果存在&#xff0c;返回 true…

Linux:进程概念(三.详解进程:进程状态、优先级、进程切换与调度)

上次讲了进程这些内容&#xff1a;Linux&#xff1a;进程概念&#xff08;二.查看进程、父进程与子进程、进程状态详解&#xff09; 文章目录 1.Linux中的进程状态1.1前台进程和后台进程运行状态睡眠状态磁盘休眠状态停止状态kill指令—向进程发送信号 死亡状态 2.僵尸进程2.1僵…

iOS--runloop的初步认识

runloop的初步认识 简单认识runloopEvent looprunloop其实就是个对象NSRunloop和CFRunLoopRef的依赖关系runloop与线程runloop moderunloop sourceCFRunLoopSourceCFRunLoopObserverCFRunLoopTimer runloop的实现runloop的获取添加ModeCFRunLoopAddCommonMode 添加Run Loop Sou…

C语言 | Leetcode C语言题解之第79题单词搜索

题目&#xff1a; 题解&#xff1a; int directions[4][2] {{0, 1}, {0, -1}, {1, 0}, {-1, 0}};bool check(char** board, int boardSize, int boardColSize, int** visited, int i, int j, char* s, int sSize, int k) {if (board[i][j] ! s[k]) {return false;} else if (…

NSSCTF中的web学习(md5())

目录 MD5的学习 [BJDCTF 2020]easy_md5 [LitCTF 2023]Follow me and hack me [LitCTF 2023]Ping [SWPUCTF 2021 新生赛]easyupload3.0 [NSSCTF 2022 Spring Recruit]babyphp MD5的学习 md5()函数&#xff1a; md5($a)&#xff1a;返回a字符串的散列值 md5($a,TRUE)&…

AWS云优化:实现性能和成本的最佳平衡

随着企业数字化转型的加速&#xff0c;对云计算平台的需求也不断增长。AWS作为云计算行业的领导者之一&#xff0c;提供了广泛的云服务和解决方案&#xff0c;帮助企业实现业务的创新和发展。在AWS云上部署应用程序和服务后&#xff0c;对其进行优化是至关重要的&#xff0c;以…

flutter报错

组件相关 type ‘List’ is not a subtype of type ‘List’ children: CardList.map((item) > Container( 加上 *** < Widget>*** 正常 type ‘(dynamic, dynamic) > Container’ is not a subtype of type ‘(CardType) > Widget’ of ‘f’ children: CardL…

YOLO系列笔记(十四)——Compute Canada计算平台及其常见命令介绍

Compute Canada平台及其常见命令介绍 前言优势使用方法1. 检查模块不带版本号带版本号 2. 加载模块3. 检查模块是否加载成功4. 创建虚拟环境5. 编写作业脚本6. 提交作业7. 监控作业状态8. 查看作业开始预计时间9. 查看作业的详细输出10. 取消作业 注意结语 前言 大家好&#x…

【吃透Java手写】4-Tomcat-简易版

【吃透Java手写】Tomcat-简易版-源码解析 1 准备工作1.1 引入依赖1.2 创建一个Tomcat的启动类 2 线程池技术回顾2.1 线程池的使用流程2.2 线程池的参数2.2.1 任务队列&#xff08;workQueue&#xff09;2.2.2 线程工厂&#xff08;threadFactory&#xff09;2.2.3 拒绝策略&…

表面的相似,本质的不同

韩信与韩王信&#xff0c;两个韩信的结局都是被刘邦所杀&#xff0c;似乎结局类似。但是&#xff0c;略加分析&#xff0c;就会发现其中存在本质的区别。 韩信属于必杀。他的王位是要来的&#xff0c;有居功自傲的本意&#xff0c;功高震主而且毫不避讳。而且年轻&#xff0c;…

Acwing2024蓝桥杯FloodFill

AcWing 687. 扫雷 模拟以下样例(10X10): 把扫雷地图转变为数字记录的地图:地雷记作-1,其余表示8个方向有几个地雷,完成后如下图: 接着搜索所有0联通块(为红色矩形),并且把联通块附近不是地雷的点(红色圆形)全标记为-1,如下图: 而答案就是当前该图中大于0的数的数目之和,再加上…

《数据结构与算法之美》学习笔记一

前言&#xff1a;今天开始学习极客时间的课程《数据结构与算法之美》。为撒要学习这个&#xff1f;因为做力扣题太费劲了&#xff0c;自己的基础太差了&#xff01;所以要学习学习。开一个系列记录一下学习笔记。认真学吧&#xff0c;学有所获才不负韶华&#xff01;之前就学过…

【算法】滑动窗口——找到字符串中所有字母异位词

本节博客是对题目——找到字符串中所有字母异位词的从读题到代码实现以及优化的详细解读&#xff0c;有需要借鉴即可。 目录 1.题目2.滑动窗口 哈希数组3.异位词优化4.总结 1.题目 题目链接&#xff1a;LINK 首先来解释一下什么是异位词&#xff0c;所谓“异位词”&#xf…

show profile

功能 当你执行一个复杂的 SQL 查询时&#xff0c;这个命令可以帮助你了解查询的各个部分花费了多少时间&#xff0c;从而找到可能的性能瓶颈。默认情况下&#xff0c;参数处于关闭状态&#xff0c;并保存最近15次的运行结果 开启 查看是否支持 SHOW VARIABLES LIKE profili…

【XR806开发板试用】试用SWD+Jlink调试

XR806开发板&#xff0c;只能使用编写代码&#xff0c;然后通过UART下载&#xff0c;没法在线debug&#xff0c; 效率会差很多&#xff0c;官方没有提供这一方面的资料。 先查CPU&#xff0c; 官方介绍是arm-china的MC1&#xff0c;通过armv8 Architecture refenence manual资料…

跨境电商行业蓬勃发展,武汉星起航引领卖家孵化新潮流

近年来&#xff0c;我国跨境电商行业在政府的大力扶持下呈现出强劲的发展势头。随着国内制造业结构的加速调整与居民消费需求升级态势的持续凸显&#xff0c;跨境出口规模占比稳步提升&#xff0c;跨境进口规模同样不断扩大&#xff0c;行业市场规模持续增长。在这一背景下&…

QT学习(4)——自定义控件

目录 引出自定义一个控件自定义控件定义方法函数widget窗口调用函数 总结 引出 QT学习&#xff08;4&#xff09;——自定义控件 自定义一个控件 自定义控件定义方法函数 #include "smallwid.h" #include "ui_smallwid.h"SmallWid::SmallWid(QWidget *par…

redis抖动问题导致延迟或者断开的处理方案

目录&#xff1a; 1、使用背景2、redis重试机制3、redis重连机制4、其他一些解决redis抖动问题方案 1、使用背景 客户反馈文件偶现打不开&#xff0c;报错现象是session not exist&#xff0c;最终定位是redis抖动导致的延迟/断开的现象&#xff0c;最终研发团方案是加入redis…

Mapreduce | 案例

根据提供的数据文件【test.log】 数据文件格式&#xff1a;姓名,语文成绩,数学成绩,英语成绩 完成如下2个案例&#xff1a; &#xff08;1&#xff09;求每个学科的平均成绩 &#xff08;2&#xff09;将三门课程中任意一门不及格的学生过滤出来 &#xff08;1&#xff09;求每…