mysql的mvcc

ops/2025/1/22 16:42:51/

快速搞懂mvcc

  • 全称 multi-version concurrency control 多版本并发控制。
  • 自动开启事务
  • undo log
  • 读视图(read_view)
  • 结果过滤
  • mvcc只在读已提交和可重复读隔离级别下运作
  • 读已提交隔离级别下,
  • 可重复读隔离级别下,
  • 总的来说mvcc是为了提高数据库并发性能而设计的,它实现了读已提交。为了保证并发性能,它本身不加锁。它只在读已提交和可重复读隔离级别下工作。
  • 读已提交隔离级别下,
    • 防止不可重复读:
    • 防止幻读:

全称 multi-version concurrency control 多版本并发控制。

自动开启事务

MySQL默认每个对数据库进行修改的SQL语句都会自动开启事务:insert into ,update,delete from 另外加锁的SQL语句也会自动开启事务:select * from table_name lock in share mode, select * from table_name where condition for update。

undo log

每个事务在修改某条记录的时候都会先将老数据备份入undo log中,然后新增一条记录,并在隐藏字段db_tx_id中记录新增这个条数据的事务id,在隐藏字段db_roll_pointer中记录刚刚备份的原数据的db_row_id(db_row_id也是隐藏字段)。这样每个事务对数据的修改并没有覆盖原有数据。事务提交后,就处于不活跃状态。

读视图(read_view)

每个事务读取数据时会创建一个读视图(read_view),read_view 包含:活跃的事务id列表,最大事务id,最小事务id,创建读视图的事务id。事务id都是自增长的,值越大,说明创建的时间越晚。

结果过滤

然后用read_view过滤查询结果:
查询结果中db_tx_id>最大事务id,说明该结果是由读视图创建后的事务创建的,应不可见,丢弃;
db_tx_id<最小事务id,说明该结果在读视图创建前就已经提交,应可见;
最小事务id<=db_tx_id<=最大事务id,db_tx_id不在活跃的事务id列表中,说明该结果已经提交,应可见,db_tx_id在活跃的事务id列表中,则说明此创建该结果的事务还没提交,该结果应不可见。
这样保证了每个并发事务都读取已提交的结果,而且整个读取过程没有解锁,并发性能得到提升。

mvcc只在读已提交和可重复读隔离级别下运作

mvcc在读已提交和可重复读模式下运行,mvcc最主要的就是实现多个并发事务读已提交的数据,所以读未提交隔离级别下允许读未提交,跟mvcc向北,mvcc是不会运作的。可序列化隔离级别下,事务都是串行的,不存在并发,所以此隔离级别下,mvcc也是不运作的。

读已提交隔离级别下,

事务每次读取都要重新创建视图,在此期间有新事务创建,也有新事务提交,所以每此创建的视图都不一样,用试图过滤出来的结果以及结果的条数也不一样,所以会出现不可重复读(读出的结果变了)和幻读(读出的结果条数变了)。

可重复读隔离级别下,

只有在刚进入事务时会创建一个视图,由于mvcc的过滤原则时只提取已提交的数据,所以随着时间的推移,进入事务之后的查询,能查出来新增的数据的事务id都是比刚进入事务时查出来的数据事务id大,新的数据不会被筛选出来
。所以筛选结果跟第一次一样。此隔离级别下可以保证可重复读,但有些新增或删除的数据可能已提交(第一次没有筛选出来的数据),而活跃的事务id没有更新,导致本该读出来的数据没有读出来,所以避免不了幻读。

总的来说mvcc是为了提高数据库并发性能而设计的,它实现了读已提交。为了保证并发性能,它本身不加锁。它只在读已提交和可重复读隔离级别下工作。

读已提交隔离级别下,

防止不可重复读:

1、将事务隔离级别设为可重复读(推荐)。
2、使用共享(读锁 select…in share mode)(不推荐)。
3、使用排他锁(写锁 select…for update)(不推荐)。

防止幻读:

1、将事务隔离级别设为可重复读,然后使用排他锁select… for update,会自动应用间隙锁(推荐)
2、使用排他锁select… for update,条件用主键筛选,会应用间隙锁(推荐)
3、应用程序自己确保更新的数据条数没有发生变化。


http://www.ppmy.cn/ops/152234.html

相关文章

springboot 配置多数据源以及动态切换数据源

场景 我们springboot项目&#xff0c;通常会有多个数据库&#xff0c;例如mysql,vertica,postgresql等等数据库&#xff0c;通常我们需要动态切换使用我们想要的数据库&#xff0c;这时候就需要配置多数据源了 多数据源特性 支持多数据库类型&#xff1a;例如&#xff0c;同…

IOC有什么优势

IOC&#xff08;控制反转&#xff0c;Inversion of Control&#xff09; 是一种设计原则&#xff0c;广泛应用于软件开发中&#xff0c;尤其是面向对象编程中。IOC 的主要优势体现在以下几个方面&#xff1a; 1. 解耦合&#xff08;Decoupling&#xff09; 减少依赖性&#x…

map和set的使用(一)详解

文章目录 序列式容器和关联式容器map和set的介绍set构造和迭代器遍历和insertfinderaseswapclearcountlower_bound和upper_boundmultiset和set的对比 set的二个题目题目解析算法原理代码介绍一个找差集的算法同步算法题目解析算法原理代码 map构造遍历initiaizer_list 序列式容…

【2024年CSDN平台总结:新生与成长之路】

&#x1f4ab;引言 2024年已经过去&#xff0c;回顾这一年&#xff0c;所有的经历依然历历在目。以“经验”为动力&#xff0c;我正迈向2025年。回顾自己在CSDN平台上的创作之路&#xff0c;收获满满、成长颇多&#xff0c;也有许多宝贵的感悟。接下来&#xff0c;我将分享这一…

[STM32 HAL库]串口中断编程思路

一、前言 最近在准备蓝桥杯比赛&#xff08;嵌入式赛道&#xff09;&#xff0c;研究了以下串口空闲中断DMA接收不定长的数据&#xff0c;感觉这个方法的接收效率很高&#xff0c;十分好用。方法配置都成功了&#xff0c;但是有一个点需要进行考虑&#xff0c;就是一般我们需要…

Java Web开发高级——单元测试与集成测试

测试是软件开发的重要环节&#xff0c;确保代码质量和功能的正确性。在Spring Boot项目中&#xff0c;单元测试和集成测试是常用的两种测试类型&#xff1a; 单元测试&#xff1a;测试单个模块&#xff08;如类或方法&#xff09;是否按预期工作。集成测试&#xff1a;测试多个…

StackOrQueueOJ3:用栈实现队列

目录 题目描述思路分析开辟队列入队列出队列 代码展示 题目描述 原题&#xff1a;232. 用栈实现队列 思路分析 有了前面的用队列实现栈的基础我们不难想到这题的基本思路&#xff0c;也就是用两个栈来实现队列&#xff0c;&#xff08;栈的实现具体参考&#xff1a;栈及其接口…

dl学习笔记:(7)完整神经网络流程

完整神经网络流程 反向传播链式求导 代码实现反向传播动量法Momentum开始迭代为什么选择小批量TensorDataset与DataLoader 反向传播 由于本节的公式比较多&#xff0c;所以如果哪里写错了漏写了&#xff0c;还请帮忙指出以便进行改正&#xff0c;谢谢。 在前面的章节已经介绍过…