mysql的mvcc

devtools/2025/1/21 21:54:39/

快速搞懂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/devtools/152432.html

相关文章

2025美赛Latex模板可直接运行!O奖自用版

目录 01 预览图02 Latex模板main.texeasymcm.sty 2025年美国大学生数学建模大赛&#xff08;2025年1月23日&#xff09;马上开始啦&#xff0c;大家一定要提前准备好模板&#xff0c;Latex或者是Word都可以&#xff0c;这里我整理了之前比赛用到的模板&#xff0c;并进行了一些…

在 JIRA 中利用仪表盘功能生成 Bug 相关图表的手册

引言 JIRA 是 Atlassian 推出的项目管理工具&#xff0c;广泛应用于软件开发、团队协作和问题跟踪。对于开发团队和项目经理而言&#xff0c;能够清晰地了解当前 Bug 状态、优先级分布及进展情况至关重要。JIRA 提供了强大的 仪表盘功能&#xff0c;让用户能够通过各种图表直观…

magic-dash:纯Python轻松开发网页应用

来源&#xff1a;Python大数据分析 费弗里 大家好我是费老师&#xff0c;今天要给大家介绍的开源Python项目magic-dash&#xff0c;提供了一系列内置的「纯Python」网页应用项目模板&#xff0c;通过执行简单的终端命令&#xff0c;即可快速生成对应类型的网页应用项目工程&…

Vue3轮播图左右联动

1、轮播图部分&#xff0c;右边鼠标移入&#xff0c;左边对应展示轮播图 可以在swiper 官网 Swiper中文网-轮播图幻灯片js插件,H5页面前端开发 选择vue中使用swiper npm i swiper 左右两边的联动&#xff1a;左边的轮播图和右边的小的列表他们的列表组成结构是一样的&#…

基于Spring Boot3 + Vue3 + JDK17的现代化的Java应用开发框架

快速启动 Guns v8前端启动 前端需要使用Node 20&#xff0c;请先安装node20&#xff0c;请使用yarn启动&#xff0c;具体启动方法如下&#xff1a; # 安装依赖 yarn# 启动前端项目 yarn run dev# 打包 npm run buildGuns v8后端启动 以下为后台启动的过程&#xff1a; 重要…

随遇随记篇

vue 函数 unref() 获取原始值 ref 定义的属性 需要 .value 才能拿到值&#xff0c;unref 直接返回原始值&#xff1b;若属性不是ref 定义的&#xff0c;也是直接返回原始值&#xff1b; /* description: 是否必填*/required?: boolean | Ref<boolean>.....let value …

JavaScript 拖拽与观察者模式的实现及应用

前言 本文将通过几个具体的代码片段&#xff0c;深入探讨 JavaScript 中的拖拽功能和观察者模式&#xff08;发布-订阅模式&#xff09;的实现及其应用场景。 这些代码片段不仅展示了如何实现这些功能&#xff0c;还解释了其背后的原理和实际用途。通过阅读本文&#xff0c;读…

小程序疫苗预约网站系统ssm+论文源码调试讲解

第4章 系统设计 一个成功设计的系统在内容上必定是丰富的&#xff0c;在系统外观或系统功能上必定是对用户友好的。所以为了提升系统的价值&#xff0c;吸引更多的访问者访问系统&#xff0c;以及让来访用户可以花费更多时间停留在系统上&#xff0c;则表明该系统设计得比较专…