运维.售后
论坛
潜水/灌水快乐,沉淀知识,认识更多同行。
ToB圈子
加入IT圈,遇到更多同好之人。
朋友圈
看朋友圈动态,了解ToB世界。
博客
Blog
ToB门户
了解全球最新的ToB事件
排行榜
Ranklist
文库
业界最专业的IT文库,上传资料也可以赚钱
下载
分享
Share
导读
Guide
相册
Album
记录
Doing
搜索
本版
文章
帖子
ToB圈子
用户
免费入驻
产品入驻
解决方案入驻
公司入驻
案例入驻
登录
·
注册
只需一步,快速开始
账号登录
立即注册
找回密码
用户名
Email
自动登录
找回密码
密码
登录
立即注册
首页
找靠谱产品
找解决方案
找靠谱公司
找案例
找对的人
专家智库
悬赏任务
圈子
SAAS
ToB企服应用市场:ToB评测及商务社交产业平台
»
论坛
›
软件与程序人生
›
后端开发
›
Java
›
事物的隔离性和MVCC
事物的隔离性和MVCC
饭宝
金牌会员
|
2022-9-16 17:20:43
|
显示全部楼层
|
阅读模式
楼主
主题
924
|
帖子
924
|
积分
2772
事物的隔离性
mysql的服务端是支持多个客户端同时与之连接的,每个客户端可能还并发了好几个连接,所以mysql是需要同时处理很多事情的,每一件独立的事情就叫做事务。我们知道事务有一个叫隔离性的特性,隔离性理论上是指在某个事物对某个数据进行访问时,其他的事务就应该排队知道访问数据的事务提交才能继续访问该数据。但是这样对性能的影响就太大了,但是我们又必须保持一定的隔离性,所以就需要折中一下。
事务并发可能的问题
先来看看不保证绝对的隔离性会遇到哪些问题呢
脏写
如果一个事务修改了另一个未提交事务修改过的数据,这就意味着发生了脏写。
脏读
如果一个事务读到了另一个未提交事务修改过的数据,这就意味着发生了脏读。
不可重复读
如果同一个事务中能读到其他事务提交后的最新值,这时其他事务对这个数据进行的每次改动都会让该事务读到不同最新值,这就意味着发生了不可重复读。
幻读
如果一个事务根据某些查出一些记录,之后另一个事务又向表中插入了符合这些条件的记录,该事务再次用该条件查询的时候,就会查出上次查没查到的数据即另一个事务刚插入的数据,这就是幻读。
小贴士:
不可重复读和幻读确实有点相似,但不可重复读重点在于update和delete,而幻读的重点在于insert。对于前者,要避免只需锁住满足条件的已有记录即可,避免后者就需要锁住满足条件的记录(包括存在的和不存在的),不存在的记录如何才能锁住呢?所以锁的范围需要扩大到满足条件的相邻范围的记录(临键锁)
事务的隔离级别
这时就出现了一个标准用来定义上面说的折中的程度,在SQL标准中定义了4个隔离级别:
READ UNCOMMITTED:读未提交
READ COMMITTED:读已提交
REPEATABLE READ:可重复读
SERIALIZABLE:可串行化
SQL标准中规定,针对不同的隔离级别并发事务可以发生不同严重程度的问题
MVCC
MVCC解决了事务并发时读和写同时进行互不影响的问题,从而提升系统性能。mvcc并不能解决完全解决脏读和不可重复读的问题,如果innoDB只有mvcc没有锁,那么当前事务确实没办法读取到未提交的数据,但是可以修改。
对于读已提交和可重复读的事务来说,都必须保证读到的记录是已经提交了的事务修改的记录,所以如果想做到读写互不影响,核心问题就是读取记录时需判断版本链中的哪个版本是对当前事务可见。
MVCC原理
对于innoDB存储引擎来说,每张表中都含有两个必要的隐藏列trx_id和roll_pointer。每次对某条记录进行改动时,都会把旧的版本写入到 undo日志中,然后在这个roll_pointer列中存储旧版本在undo日志的地址,可以通过它来找到该记录修改前的信息,同时将进行改动的事务id写入trx_id列。
在可重复读的隔离模式下每个事务都会生成一个 ReadView ,主要包含4个重要的内容:
m_ids :表示在生成 ReadView 时当前系统中活跃的读写事务的 事务id 列表。
min_trx_id :表示在生成 ReadView 时当前系统中活跃的读写事务中最小的 事务id ,也就是
m_ids 中的最 小值。
max_trx_id :表示生成 ReadView 时系统中应该分配给下一个事务的 id 值。
creator_trx_id :表示生成该 ReadView 的事务的 事务id 。
有了这个 ReadView ,这样在访问某条记录时,只需要按照下边的步骤判断记录的某个版本是否可见:
如果被访问版本的 trx_id 属性值与 ReadView 中的 creator_trx_id 值相同,意味着当前事务在访问它自己 修改过的记录,所以该版本可以被当前事务访问。
如果被访问版本的 trx_id 属性值小于 ReadView 中的 min_trx_id 值,表明生成该版本的事务在当前事务生 成 ReadView 前已经提交,所以该版本可以被当前事务访问。
如果被访问版本的 trx_id 属性值大于 ReadView 中的 max_trx_id 值,表明生成该版本的事务在当前事务生 成 ReadView 后才开启,所以该版本不可以被当前事务访问。
如果被访问版本的 trx_id 属性值在 ReadView 的 min_trx_id 和 max_trx_id 之间,那就需要判断一下 trx_id 属性值是不是在 m_ids 列表中,如果在,说明创建 ReadView 时生成该版本的事务还是活跃的,该版本不可以被访问;如果不在,说明创建 ReadView 时生成该版本的事务已经被提交,该版本可以被访问。
如果某个版本的数据对当前事务不可见的话,那就顺着版本链找到下一个版本的数据,继续按照上边的步骤判断 可见性,依此类推,直到版本链中的最后一个版本。如果最后一个版本也不可见的话,那么就意味着该条记录对 该事务完全不可见,查询结果就不包含该记录。
上面两段引用来自于《MySQL是怎样运行的:从根儿上理解MySQL》,我觉得已经很明白了。
我写文章都是力求正确,但水平有限,欢迎大佬斧正。
相关资源:
MySQL是怎样运行的:从根儿上理解MySQL
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
本帖子中包含更多资源
您需要
登录
才可以下载或查看,没有账号?
立即注册
x
回复
使用道具
举报
0 个回复
倒序浏览
返回列表
快速回复
高级模式
B
Color
Image
Link
Quote
Code
Smilies
您需要登录后才可以回帖
登录
or
立即注册
本版积分规则
发表回复
回帖并转播
回帖后跳转到最后一页
发新帖
回复
饭宝
金牌会员
这个人很懒什么都没写!
楼主热帖
53基于java的资源博客论坛系统设计与实 ...
zotero+坚果云实现多pc端及iPad同步管 ...
天涯神贴合集500篇(2023最新) ...
Android——一个简单的记账本APP ...
需求:清空三个月前的操作日志,并生成 ...
面试官:@Configuration 和 @Component ...
【分布式计算】学习笔记(期末复习) ...
Python潮流周刊#5:并发一百万个任务要 ...
PerfView专题 (第十一篇):使用 Diff ...
nginx 常用指令配置总结
标签云
存储
服务器
快速回复
返回顶部
返回列表