事务---MVCC

MVCC(Multi-Version Concurrent Control,即多版本并发控制)

每条记录生成版本链,来解决事务的隔离级别问题。

每条记录有两个隐藏列,trx_id:事务ID和指向上该条记录上个版本的指针。

 如:Mysql默认Repeated Read

目的:保证在同一事务中两次读取数据一致。

事务A在第一次读取数据时生成一个ReadView,记录当前活动事务的集合。再次读取数据的时候会判断记录的哪些版本是不可见的,取出该记录第一条可见的版本作为记录值返回。

判断依据ReadView记录的活动集合。若某版本的trx_id在集合中,则不可见。大于最大也不可见。若小于集合里最小的trx_id则可见。因为trx_id是递增的,比活动事务里的trx_id都小说明生成该条记录的事务在事务A第一次读生成ReadView之前就已经提交了。以此保证两次读出数据一致。

相当于快照,在第一读的时候生成快照,在此刻已经创建的事务,或在次之后创建的事务对数据所做的修改都不可见。通过事务ID过滤。

扫描二维码关注公众号,回复: 11056442 查看本文章

 

MVCC是为了解决脏读,不可重复读等读相关的隔离级别。只有读的时候生成ReadView。Update,Insert等不生成。

平时的select,update,insert等语句都是事务。在执行一条语句时mysql会自动开启事务执行完自动提交。可通过查看 show variables LIKE 'autocommit' 是否开启自动提交。https://blog.csdn.net/wx145/article/details/82740737

每条语句都是事务,则trx_id会不断增大,到最大则归零,那一时刻会出现脏读等问题,不过要好几十年后才能到最大值。自增主键到达极限时,不会归零,再创建的话会插入最大值,会报主键冲突。 https://www.cnblogs.com/gaosf/p/11189127.html

 

验证:

1.会话1开启事务:

 事务ID:一个活跃事务:

 2.会话2开启另一个事务:

 生成另一个活跃事务:

3. 事务2执行插入操作:

 4.事务2查询:

 5:事务1查询:

 6.事务1修改:此时阻塞,因为事务2还未提交。超过一定时间会报超时。

 

 7、事务2提交

无论从会话1还是会话2查都只剩一个活动事务

 

8.会话1查询。此时可以看出mysql的MVCC防止了幻读。多次读取都只有一条记录,结果一致。

 9.会话1更新,会话2插入的那条记录。

 10.会话1查询:又出现了幻读。

第九步由于修改了新增的记录,导致该条记录的最新版本的trx_id是当前事务的id,当前事务的版本是可见的,所以本来不可见的又变成了可见。

虽然正常场景MVCC是可以防止幻读的,单这种极端场景只靠MVCC就没法防止幻读的。

猜你喜欢

转载自www.cnblogs.com/tommaoxiaoqi/p/12757601.html