您现在的位置是:首页 >其他 >少年,你可听说过MVCC?网站首页其他

少年,你可听说过MVCC?

Fireplusplus 2024-07-11 05:33:02
简介少年,你可听说过MVCC?

:切!这谁没听过,不就是多版本并发控制么~

早在亘古时期,修真界就流传着一门mysql功法,将其修至小乘境界,足以纵横一方。。。不乏也有走火入魔者,为祸一方~

Serializable篇

强制事务排序,串行化执行事务。技能之间不存在冲突,就是滚键盘~能不能再快点呢,技能前摇那么长,一次性放俩多好^_^

Read Uncommitted篇

某个不知名大牛路过你这样搞一下试试:

事务1事务2
select * from table where key = 1;
update table set name="da niu" where key = 1;
select * from table where key = 1;

看到了没,事务1第一次查询的结果和第二次查询的结果还能一样吗,this is 脏读!

Read Committed篇

原来这就是脏读啊,那我等到事务2提交之后再读,不就ok了吗^_^

事务1事务2
select * from table where key = 1;
update table set name="da niu" where key = 1;
commit
select * from table where key = 1;

你能说事务1第二次读出来的数据是脏的吗?不能。但是事务一两次读取的数据结果仍然不同,这叫做不可重复读问题。

Repeatable Read篇

这还怎么搞。。。

据说是有个头秃哥,搞了叫Read View个东西出来。Read View可以认为是数据库的一个内部快照,根据事务的隔离级别,决定在事务开始时,该事务能看到什么信息。就是说通过Read View,事务可以知道此时此刻能看到哪个版本的数据记录(有可能不是最新版本的,也有可能是最新版本的)。可重复读、读已提交、读未提交,这几个隔离级别都会使用Read View。

ReadView中主要包含几个比较重要的字段:

creator_trx_id创建Read View事务的id
trx_ids生成Read View时活跃的事务id集合
up_limit_idtrx_ids中最小的事务id
low_limit_id生成Read View时下一个可分配的事务id

有了这些id信息,即使事务2已提交的情况下,也不会出现可重复读的问题了:

事务1事务2
select * from table where key = 1;(获取Read View)
update table set name="da niu" where key = 1;
commit
select * from table where key = 1;(获取Read View)

第一次查找获取Read View,当前事务id为0,该行数据的trx_id小于事务1Read View中的up_limit_id,即该行数据为事务1创建之前产生的,故而对事务1可见;

第二次查找,该行数据的trx_id被事务2改为了自己的事务id,使得trx_id在事务1Read View的trx_ids中,说明改行数据由创建事务1时的其它活跃事务更新过,故而使其对事务1不可见;

:数据就没。。没了?

当然不会,还记得undo log吗,记录了数据库操作的执行逻辑。我们对这行数据再做一次相反的执行逻辑,就能拿到修改前的数据了^_^

类似的,如果在事务1创建之后,又有事务3被创建,并修改了key=1的数据,则该行记录的trx_id大于等于事务1Read View中的low_limit_id,也可以知晓当前数据被修改过来。继续根据undo log恢复以前版本的数据即可。

这就是多版本并发控制了。。。

幻读篇

那幻读又是啥呢??

前面说了不可重复读的问题,是说同一个事务中,多次查询同一条记录,查询结果不同的问题;

幻读其实也很简单,说的是同一个事务中,查询多次,查询结果记录条数不一致的问题;

明白了吧,一个是说记录本身的内容发生变化,另一个说的是记录的条数。

显然,通过MVCC,也能解决幻读的问题了

风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。