首页 > 数据库 >简单MySQL例子演示MVCC

简单MySQL例子演示MVCC

时间:2023-05-29 15:47:43浏览次数:31  
标签:演示 记录 MVCC T2 T1 trx MySQL NULL id

一沈秋园,满庭霜落,云烟北桥夜连城

MVCC 是多版本并发控制的缩写,是一种数据库和编程语言中常用的并发控制方法。它通过保存数据的历史版本,实现对数据库的高效访问。

MySQL 中 MVCC 主要是通过行记录中的隐藏字段(隐藏主键 row_id,事务ID trx_id,回滚指针 roll_pointer),undo_log(版本链),ReadView(一致性试图)来实现的。

下面是一个简单的例子:

假设有一个表 t,有两个字段 id 和 name,初始状态如下:

id name
1 A
2 B

 

 

 

现在有两个事务 T1 和 T2,T1 在可重复读(Repeatable Read)隔离级别下,T2 在读已提交(Read Committed)隔离级别下。

T1 和 T2 的执行过程如下:

1,T1 开始,执行 select * from t; 得到结果:

id name
1 A
2 B

 

 

 

2,T2 开始,执行 update t set name = 'C' where id = 1;  此时表 t 的行记录发生变化,变为:

id name row_id trx_id roll_pointer
1 C 100 200 300
2 B 101 NULL NULL

 

 

 

此时 undo log 中记录了 id 为 1 的行记录的旧版本:

id name row_id trx_id roll_pointer
1 A 300 NULL NULL

 

 

3,T1 再次执行 select * from t; 此时由于 T1 是可重复读隔离级别,它会根据自己的 ReadView 来判断那些记录是可见的。

ReadView中保存了当前活跃事务的 ID 列表,以及当前系统最小和最大事务ID。

假设 T1 的 ReadView 如下:

min_trx_id max_trx_id active_trx_id
100 200 [200]

 

 

那么T1会根据以下规则来判断行记录是否可见:

  • 如果行记录的trx_id为NULL,或者小于min_trx_id,说明该行记录是在T1之前就已经提交的,对T1可见。
  • 如果行记录的trx_id等于T1自己的trx_id,说明该行记录是T1自己修改的,对T1可见。
  • 如果行记录的trx_id大于max_trx_id,说明该行记录是在T1之后才修改的,对T1不可见。
  • 如果行记录的trx_id在min_trx_id和max_trx_id之间,并且不在active_trx_ids中,说明该行记录是在T1之前就已经提交的,对T1可见。
  • 如果行记录的trx_id在min_trx_id和max_trx_id之间,并且在active_trx_ids中,说明该行记录是由其他未提交事务修改的,对T1不可见。

根据这些规则,T1会发现 id 为1的行记录不可见,因为它的 trx_id 为 200,在 active_trx_ids 中。所以 T1 会沿着回滚指针找到 undo log 中的旧版本,并判断它是否可见。

旧版本的 trx_id 为NULL,小于 min_trx_id,所以对 T1 可见。因此,T1 得到结果:

id name
1 A
2 B

 

 

 

这就是MVCC的原理,通过保存数据的历史版本,实现对数据库的高效访问,保证事务的一致性和隔离性。

接下来看T2的执行过程:

4,T2 执行 commit; 提交事务,此时表 t 的行记录变为:

id name row_id trx_id roll_pointer
1 C 100 NULL NULL
2 B 101 NULL NULL

 

 

 

undo log中的旧版本被删除。

5,T2再次执行 select * from t; ,此时由于 T2 是读已提交隔离级别,它会根据自己的 ReadView 来判断哪些行记录是可见的。

ReadView 中保存了当前活跃事务的 ID列表,以及当前系统最小和最大事务ID。

假设 T2 的 ReadView 如下:

min_trx_id max_trx_id active_trx_id
201 201 []

 

 

那么T2会根据以下规则来判断行记录是否可见:

  • 如果行记录的 trx_id 为 NULL,或者小于 min_trx_id,说明该行记录是在 T2 之前就已经提交的,对 T2 可见。
  • 如果行记录的 trx_id 等于 T2 自己的trx_id,说明该行记录是 T2 自己修改的,对 T2 可见。
  • 如果行记录的 trx_id 大于 max_trx_id,说明该行记录是在 T2 之后才修改的,对 T2 不可见。
  • 如果行记录的 trx_id 在 min_trx_id 和 max_trx_id 之间,并且不在 active_trx_ids 中,说明该行记录是在 T2 之前就已经提交的,对 T2 可见。
  • 如果行记录的 trx_id 在 min_trx_id 和 max_trx_id 之间,并且在 active_trx_ids 中,说明该行记录是由其他未提交事务修改的,对 T2 不可见。

根据这些规则,T2 会发现 id 为 1 和 id 为 2 的行记录都可见,因为它们的 trx_id 都为 NULL,小于 min_trx_id。因此,T2 得到结果:

id name
1 C
2 B

标签:演示,记录,MVCC,T2,T1,trx,MySQL,NULL,id
From: https://www.cnblogs.com/zhangzhongkun/p/17440487.html

相关文章

  • docker部署ZeLog项目(Tomcat+MySQL+ZrLog)
    一.docker的安装1.1、在安装dockers之前,建议关闭Centos7.9防火墙[root@192~]#systemctlstopfirewalld[root@192~]#setenforce0 setenforce是Linux的selinux防火墙配置命令执行setenforce0表示临时关闭selinux防火墙1.2、通过yum在线安装Docker服务[root@localhos......
  • mysql快速对比两个数据库表名的差异
    2023年5月29日14:51:02因为正式库老是和测试库有差1-2张表,表也有100张了,排除差异有点麻烦SELECTtable_nameFROMinformation_schema.TABLESWHEREtable_schema='数据库名'这样就得到两个数据库表名列新建两个txt,database.txt和database_test.txt选中两个文件,右键使用T......
  • 玩转MySQL数据库之SQL优化之慢查询
    本系列为:MySQL数据库详解,为千锋资深教学老师独家创作,致力于为大家讲解清晰MySQL数据库相关知识点,含有丰富的代码案例及讲解。如果感觉对大家有帮助的话,可以【关注】持续追更~文末有本文重点总结,技术类问题,也欢迎大家和我们沟通交流!前言从今天开始本系列文章就带各位小伙伴学习......
  • MySQL索引(一)
    雨喝醉了,小路摇摇晃晃,倒在我怀里1,B树和B+树之间的区别是什么?2,Innodb中的B+树有什么特点?3,什么是Innodb中的page?4,Innodb中的B+树是怎么产生的?5,什么是聚簇索引?6,Innodb是如何支持范围查找能走索引的?7,什么是联合索引?对应的B+树是如何产生的?8,什么是最左前缀原则?......
  • mysql、sqlserver、oracle分页,java分页统一接口实现
    定义:pageStart起始页,pageEnd终止页,pageSize页面容量oracle分页:rownum numfrom(实际传的SQL)where rownum<=pageEnd)wherenum>=pageStartsqlServer分页:           select*from(select top 页面容量from(select top字段Adesc)astemptable2orderb......
  • MYSQL round()函数
    在mysql中,round函数用于数据的四舍五入,它有两种形式:1、round(x,d) ,x指要处理的数,d是指保留几位小数这里有个值得注意的地方是,d可以是负数,这时是指定小数点左边的d位整数位为0,同时小数位均为0;2、round(x) ,其实就是round(x,0),也就是默认d为0;下面是几个实例1、查询: selectro......
  • mysql
    B树。b+树的区别:为什么,以及好处,坏处 。  B-树可以看成是平衡二叉树的多路树,每个节点上既存储索引关键字,又存储记录。查找时候从根节点开始查找。 B+树只有叶子结点存储记录,非叶子结点上存储关键字,mysql慢查询,如何优化。为什么选择N树,B+树 不选自,二叉树,红黑......
  • MySQL中时间函数NOW()和SYSDATE()的区别
    mysql中日期函数还是比较常用的。主要有NOW()和SYSDATE()两种,虽然都表示当前时间,但使用上有一点点区别。NOW()取的是语句开始执行的时间,SYSDATE()取的是动态的实时时间。因为NOW()取自mysql的一个变量”TIMESTAMP”,而这个变量在语句开始执行的时候就设定好了,因此在整个语句......
  • MySQL 将 字符串 转为 整数
    1、CAST(eprAStype)1)type为 SIGNEDSELECTCAST("-12"ASSIGNED);效果如下:2)type为UNSIGNEDSELECTCAST("-12"ASUNSIGNED);效果如下:2、CONVERT(expr,type)SELECTCONVERT('123',SIGNED);额外补充1、CAST和CONVERT两个函数中的type取值可以为:SIGNED,UNS......
  • ubuntu22安装docker、redis、mysql及部署net6应用
    一、更新系统软件包索引sudoaptupdate二、安装dockersudoaptinstalldocker.io三、在docker中安装Mysql拉取mysql镜像dockerpullmysql:latest查看镜像dockerimages运行容器dockerrun-itd-p3306:3306-eMYSQL_ROOT_PASSWORD=123456--namemysql......