MySQL事务隔离可重复读RR下隔离效果分析

小文blog小文 2018-11-30 10:23 270人围观

还是上文的那个数据表 

 id  name age 

 1    小文 13 

 2   小田  23

问题

Q:事务A开始事务并查询id=1的name值,事务B开启事务修改id=1的name为xiaowen并提交,事务A再次读取会是?

A:小文

Q:事务A开始事务没做操作,事务B开启事务修改id=1的name为xiaowen并提交,事务A查询id=1的name值是?

A:xiaowen

Q:事务A开始事务并查询id=1的name值,事务B开启事务修改id=2的name为xiaotian并提交,事务A读取id=2的name会是?

A:答案是小田

Q:事务A开始事务更新id=1的name值(注意这点没select是update操作),事务B开启事务修改id=2的name为xiaotian并提交,事务A读取id=2的name会是?

A:答案是xiaotian

结论

上面四个操作你有没有什么结论得出?

那就是,事务会在第一次select创建一致性视图read-view,并且是基于整个库的,所以会保证RR下的一致性读。

疑问:尼玛,缓存整个库????岂不是很慢???

这里就用到了mvcc多版本咯。

每个事务都有一个唯一的事务ID,叫transcation_id,他是事务开始时候,像系统申请的,严格按照顺序递增。

每行数据是有多个版本的,每次事务更新都会生成一个新的数据版本,并且把事务ID与这个版本标记为row trx_id。同时旧的版本也要保留,并且在新版本中,可以读取到旧版本。

也就是说,数据表中的一行记录,可能有多个版本,每个版本都有自己的trx_id。

在事务启动后,会在第一条select语句开始,找到所有已提交的trx_id的最大值,也就是最新版本,记录为up_limit_id。这样在一个事务中,只读等于up_limit_id的版本,而大于up_limit_id的版本时,会向前不断的找老版本,直到找到up_limit_id。

理解理解,再去看下上面四个问题。

那么更新呢

Q:事务A开始事务并查询id=1的age值[23],事务B开启事务修改id=1的name为25并提交,事务A update id=1 set age = age+1 ,然后Select这个age是多少?

A:26 

可能你会惊呆了,为什么会是26?不是应该是24吗?

这就是事务的更新逻辑了,它优先会读当前版本的值,而不是之前的read-view,所以它读到age是25更新后是26。

更新数据都是先读后写,只能读当前值,称为当前读(current read)!

Q:事务A开始事务并查询id=1的name值,事务A修改name为xiaowen,事务A再次读取会是?

A:废话,当然是xiaowen,这也是一致性读不会影响自己事务内的更新,自己事务内有更新的话,会读到自己的更新,但是还是读不到其他事务的更新。

总结

在RR可重复读级别下,第一次查询会找到当前最新的up_limit_id,后面的查询复用这个up_limit_id。

在RC提交读级别下,每次查询都会找到当前最新的up_limit_id。

好了,事务的隔离性就分析到这了。


转载请注明来自小文blog,本文标题:MySQL事务隔离可重复读RR下隔离效果分析

发布评论
生活是一场戏,主角当累了,你亦可成为观众,停下脚步,歇一歇