readview机制是一套基于undo log版本链条实现的读视图机制,每个事务都会生成一个readview
若为事务自己更新的数据,自己可以读到
或在你生成readview之前提交的事务所修改的值,也可读到
但若你生成readview时,就已经活跃的事务,但如果它在你生成readview之后修改的数据并提交了,此时你读不到
或你生成readview以后再开启的事务修改了数据,还提交了,也读不到
所以上面那套机制就是readview的一个原理如何基于readview实现rc?核心设计:当一个事务设置rc,他是每次发起查询,都重新生成一个readview!
数据库里有一行数据,是事务id=50的一个事务,很久以前就插入的,当前活跃事务:
事务a(id=60)
事务b(id=70)
现在事务b发起update,更新这条数据为b,所以此时数据的trx_id会变为事务b的id=70,同时生成一条undo log:
这时,事务a要发起一次查询操作,就会生成一个readview
这时事务a发起查询,发现当前这条数据的trx_id=70。即属于readview的事务id范围之间,说明是他生成readview之前就有这个活跃的事务,是这个事务修改了这条数据的值,但此时事务b还没提交,所以readview的m_ids活跃事务列表里,有[60, 70]两个id,此时根据readview机制,事务a无法查到事务b修改的值b。
接着就顺着undo log版本链条往下查找,就会找到一个原始值,发现其trx_id是50,小于当前readview里的min_trx_id,说明是他生成readview之前,就有一个事务插入了这个值并且早就提交了,因此可以查到这个原始值。
假设事务b已提交,这意味着它不再是数据库中的活跃事务。事务a下次再查询,就可以读到事务b修改过的值了。那到底是怎么让事务a能够读到提交的事务b修改过的值呢?
让事务a下次发起查询,再生成一个readview,数据库内活跃的事务只有事务a,因此:
min_trx_id是60
mac_trx_id是71
m_ids=60,事务b的id=70不会出现在m_ids活跃事务列表
此时事务a再次基于这个readview去查询,会发现这条数据的trx_id=70,虽然在readview的min_trx_id和max_trx_id范围之间,但是此时并不在m_ids列表内,说明事务b在生成本次readview之前就已提交。当您进行查询操作时,您将能够查看事务b所进行的更新操作,这将导致事务a获取值b。
以上就是mysql如何实现rc事务隔离的详细内容。