当前位置:网站首页>MySQL事务并发问题和MVCC机制
MySQL事务并发问题和MVCC机制
2022-06-30 17:32:00 【z啵唧啵唧】
文章目录
MySQL事务并发问题和MVCC机制
事务并发的几种问题
1.脏读(读未提交数据)
- 脏读指的是事务读取到其他事务没有提交的数据
- 举个栗子
事务A读取表中的name,事务B将表中的张三修改称为了张老三,假设这时候事务A读取到了name为张老三,但是到最后事务B又因为其他原因回滚了数据,数据库表中的name为张三,那这就出现了问题,事务A读到的数据和数据库表中的不一致.而且这个数据变化到底是因为原因造成的事务A是不知道的
2.不可重复读(并发更新的情况下)
- 不可重复读指的是在同一次事务中前后查询不一致的问题
- 举个栗子
事务A先查询了数据库中的人员名字,之后就去处理其他的数据,之后有重复了最开始查询的内容,那么事务A预期的应该是两次查询的结果应该是一致的,因为事务A在处理其他数据的时候,没有对查询的数据做一个修改
但是问题是在事务A处理其他数据的时候,事务B对事务A查询的数据做了更新且提交了,那么事务A和事务B在并发的情况下,两次查询的结果就不一致了
但是实际的理论上我们事务A没有对数据进行更新,那么在事务A在没有提交之前,无论查询多少次数据都应该是一致的才对,这个理论情况叫做可重复的
上面并发出现的这个情况叫做不可重复读
同一个事务前后两次读取的数据不一致,就导致我们的程序不可预期不可控,这也就是不可重复读带来的危害
3.幻读(并发新增,删除这种导致数据总量发生变化的操作)
- 幻读是一次失误当中前后数据量发生变化,用户产生不可预估的问题
- 举个栗子
在这个例子当中,事务A先查询了数据库表发现有一条数据,他在删除了这个数据之后,事务B向数据库表当中插入了一条数据,事务A此时还没有提交,当事务A再次查询数据库表的收,预期结果应该是空数据,但是凭空多出来这个李四是什么鬼,这个就是这两个事务在并发情况下发生的幻读问题
事务隔离级别
其中MySQL默认的事务隔离级别是第三个:可重复读,比较特殊的要记住就是,常常说可重复读事务隔离级别能避免脏读和不可重复读,但是不能避免幻读,但是实际上如果我们的数据库使用的是InnoDB存储引擎是不存在幻读的.
获取和设置事务隔离级别的命令
- 其实一般不用设置,使用默认的就行,因为MySQL5.1之后默认使用的是InnoDB存储引擎,且默认的事务隔离级别是RR,能够避免三种并发事务问题
- 为啥InnoDB存储引擎在RR事务隔离级别下也能够避免幻读呢?这就要说说这个MVCC机制了
MVCC机制
写在前面
在MySQL的InnoDB存储引擎下 RC和RR 事务隔离级别都是基于这个MVCC(多版本并发控制)进行并发事务的控制的
然后这个MVCC是基于这个"数据版本"对并发事务进行访问的
示例分析
有四个事务ABCD其中前三个事务执行的操作都是对表中name字段进行修改
事务D执行的操作是进行数据的查询,但是仔细看事务D查询的位置还特殊的不行,第一次查询是在事务A提交之后事务B提交之前,第二次查询数据是在事务B提交之后在事务C提交之前
- 分别在RR隔离级别和RC隔离级别下分析下两次查询读取到的数据情况
RR隔离级别下
RR隔离级别是可重复读,那么就意味着在整个事务中读取到的数据是一致的那么显而易见第一次查询和第二次查询得到的数据是一致的,即name=张三
RC隔离级别下
由于RC是读已提交,只要别的事务提交数据,我就进行读取,那么实际上最后RC隔离级别下两次读到的数据分别是: 第一次:张三 第二次:张小三
显而易见RC隔离级别下出现的问题就是不可重复读
分析现象
基于UNDO_LOG的版本链
- UNDO_LOG是回滚日志,在我们进行事务处理的时候,只有增加回滚日志,当我们事务执行失败的时候要执行rollback回滚操作的时候才能够进行还原.其原理就是采用了链的方式进行组织.
- 最上面一行的数据就是我们数据库中该字段当前的数据,并且当时执行这个事务update语句的事务编号为TRX_ID = 3
- 额外附加的字段1:TRX_ID执行这个版本的数据是哪个事务执行的结果,就记录下这个事务的id
- 额外添加字段2:DB_ROLL_PTR:指针信息,指向了上一次进行版本变化的时候他的数据是什么
- 按照这个表我们就可以清楚的知道最原始的表中的数据是张三丰(假设),然后经过三次的更新之后更新为了张老三,每个数据都采用事务ID作为版本来进行标识
- UNDO_LOG如果被删除了怎么办?中间数据被删除了UNDO_LOG版本链不就断了吗?
UNDO_LOG版本链不是立即删除的,MySQL确保版本数据链不再被引用之后在进行删除,所以除了一些不可控的因素之外,一般数据都是比较完整的
ReadView
- ReadView是"快照读"SQL执行时MVCC提取数据的依据
- 所以说使用MVCC机制的前提时快照读,这也是InnoDB存储引擎下RR事务隔离级别的一种实现方式
- 如果读取方式不是快照读而是当前读,那么实现的机制就不是MVCC机制了而是使用了加锁的方式,加的是行锁和间隙锁
快照读和当前读
- 快照读:就是最普通的select查询SQL语句就是快照读
- 当前读:当指代执行下列语句时进行数据读取的方式:
insert into ...
update ...
delete ...
select ... for update
# 对当前增加了写锁
select ...lock in share mode
ReadView数据结构
- ReadView就是一个数据接结构,它包含了4个字段
读已提交(RC)场景下
在每一次执行快照读的时候生成全新的ReadView
- 第一次快照读生成的readview从图中可以看出事务2,3,4还没有提交所以当前活跃事务id:m_ids={2,3,4},最小活跃事务id:min_trx_id=2,预分配事务id:max_trx_id = 5 (因为时当前最大活跃事务id + 1所以就是4 + 1 = 5),当前事务创建者id:creator_trx_id = 4
- 第二次快照读生成的readview和第一次分析逻辑相同
版本链数据访问规则
版本链数据访问规则:
- 判断当前事务id等于creator_trx_id(4)吗?成立说明数据就是自己这个事务更改的,可以访问.
- 判断trx_id < min_trx_id(2) ? 成立则说明数据已经提交了,可以访问.
- 判断trx_id > max_trx_id(5) ? 成立则说明该事务是在readview生成以后才开启的,不允许访问.
- 判断min_trx_id(2) <= trx_id <= max_trx_id(5),成立在m_ids数据中进行对比,不存在则代表数据是已经提交的,可以进行访问.
让undo_log版本链中的版本从小到校一次带入到这个规则当中进行判断找到第一个可以访问的数据.
- 第一次生成的readview
这个快照读带入可以在trx_id = 1这个版本的时候,满足trx_id < min_trx_id(2) 说明数据已经提交可以访问所以第一次查询语句查询出来的数据就是张三.
- 第二次生成的快照读
这个快照读可以在trx_id = 2的时候满足规则中的第二条 trx_id < min_trx_id(3)说明数据已经提交了,读取的数据为张小三 !!!出现了不可重复读的现象
可重复读(RR)的场景
- 仅在第一次执行快照读时生成ReadView,后续快照读复用这个ReadView(但是存在例外)
- 那么在这样的情况下,版本链不变化,ReadView不变,那么两次读的结果肯定是一样的
- RR级别下使用MVCC能避免幻读吗? 能但是不完全能!
连续多次快照读的时候,ReadView会产生复用,没有幻读问题
但是需要注意的是:当两次快照读之间存在当前读,ReadView会重新生成,导致产生幻读
边栏推荐
- Another CVPR 2022 paper was accused of plagiarism, and Ping An insurance researchers sued IBM Zurich team
- VScode 状态条 StatusBar
- 充值满赠,IM+RTC+X 全通信服务「回馈季」开启
- CODING 正式入驻腾讯会议应用市场!
- At present, the big guys are joining the two streams of flinksql, cdcmysql and Kafka, and the results are put into MySQL or KA
- 《客从何处来》
- Hcip (Huawei Senior Network Security Engineer) (Experiment 8) (MPLS basic experiment)
- PHP uses queues to solve maze problems
- Flink系列:checkpoint调优
- Classic problem of leetcode dynamic programming (I)
猜你喜欢
The easynvr platform equipment channels are all online. What is the reason for the "network request failure" in the operation?
Vulnerability recurrence ----- 35. Uwsgi PHP directory traversal vulnerability (cve-2018-7490)
充值满赠,IM+RTC+X 全通信服务「回馈季」开启
[software testing] basic knowledge of software testing you need to know
Sword finger offer 17 Print from 1 to maximum n digits
3.10 haas506 2.0开发教程-example-TFT
Post office - post office issues (dynamic planning)
Apple Watch无法开机怎么办?苹果手表不能开机解决方法!
【TiDB】TiCDC canal_ Practical application of JSON
Dependencies tool to view exe and DLL dependencies
随机推荐
ForkJoinPool
Do you really understand the persistence mechanism of redis?
【TiDB】TiCDC canal_json的实际应用
ForkJoinPool
Flink series: checkpoint tuning
Rhai - Rust 的嵌入式脚本引擎
TiDB Dashboard里面可以写sql执行吗
抖音最新Xbogus,signature生成js逆向分析
How to solve the lock-in read-only alarm of AutoCAD Chinese language?
教你30分钟快速搭建直播间
如何利用AI技术优化独立站客服系统?听听专家怎么说!
分布式场景下,你知道有几种生成唯一ID的方式嘛?
Dependencies tool to view exe and DLL dependencies
Another CVPR 2022 paper was accused of plagiarism, and Ping An insurance researchers sued IBM Zurich team
如何做好软件系统的需求调研,七种武器让你轻松搞定
Tensorflow2 深度学习十必知
Apple Watch无法开机怎么办?苹果手表不能开机解决方法!
领导:谁再用 Redis 过期监听实现关闭订单,立马滚蛋!
MRO工业品采购管理系统:赋能MRO企业采购各节点,构建数字化采购新体系
Infineon - GTM architecture -generic timer module