MVCC:是一种解决读-写冲突的无锁并发控制
https://mp.weixin.qq.com/s/iFmvvt4DJ-_qFeb0XUh6QA
https://mp.weixin.qq.com/s/CZHuGT4sKs_QHD_bv3BfAQ
MVCC 多版本的并发控制,Multi-Version Concurrency Control。
MVCC 使得数据库读不会对数据加锁,普通的SELECT请求不会加锁(避免了加锁操作,降低了开销),提高了数据库的并发处理能力。
MVCC 保证了ACID中的I特性(隔离性),数据库可以实现 读已提交、可重复读 等隔离级别。
MVCC 实现依赖的是 undo log 与 read view。
MVCC 在MySQL InnoDB中的实现主要是为了提高数据库并发性能,用更好的方式去处理读-写冲突,
做到即使有读写冲突时,也能做到不加锁,非阻塞并发读。
MVCC 作用:
1、通过处理读写冲突的手段,提高数据库高并发场景下的吞吐性能;
2、根据 ReadView原理:每个读操作会看到一个一致性的快照(这个快照是基于整个库的),
并且可以实现非阻塞的读,用于"支持读提交、可重复读隔离级别的实现"。
3、通过 undo_log 记录数据的多个版本,这个版本可以是时间戳或者是全局递增的事务 ID,
在同一个时间点,不同的事务看到的数据是不同的。
一、Read View:进行快照读操作的时候生产的读视图(Read View),
在该session执行的快照读的那一刻,会生成数据库系统当前的一个快照。
四个重要的字段:
1、creator_trx_id :指的是"创建该 Read View 的事务的事务 id"。
2、m_ids :指的是创建 Read View 时当前数据库中"活跃且未提交的事务的事务 id 列表",注意是一个列表。
3、min_trx_id :指的是创建 Read View 时当前数据库中"活跃且未提交的事务中最小事务的事务 id",也就是 m_ids 的最小值。
4、max_trx_id :这个并不是 m_ids 的最大值,而是"创建 Read View 时当前数据库中应该给下一个事务的 id 值";
二、聚族索引记录中都包含下面两个隐藏列:
1、trx_id(行的事务ID):当一个事务对某条聚族索引记录进行改动时,
就会"把该事务的事务 id (creator_trx_id) 记录在 trx_id 隐藏列里";
2、roll_pointer(行的回滚指针):
每次对某条聚族索引记录进行改动时,都会把旧版本的记录写入到 undo_log 日志中,
然后"这个隐藏列是个指针,指向每一个旧版本记录",于是就可以通过它找到修改前的记录。
三、undo_log 日志:一条记录版本线性表(链表),undo log的链首就是最新的旧记录,链尾就是最早的旧记录。
insert undo log:代表事务在insert新记录时产生的undo log, 只在事务回滚时需要,
并且在事务提交后可以被立即丢弃。
update undo log:事务在进行update或delete时产生的undo log; 不仅在事务回滚时需要,
在快照读时也需要;所以不能随便删除;
对MVCC有帮助的实质是update undo log ,undo log 实际上就是存在 rollback segment中旧记录链。
举例:这种通过记录的版本链来控制并发事务访问同一个记录时的行为,这就叫 MVCC(多版本并发控制)。
可重复读:"指一个事务执行过程中看到的数据,一直跟这个事务启动时看到的数据是一致的"
"隔离级别是在事务期间读到的数据都是事务启动前的记录数据。"
"隔离级别是启动事务时生成一个 Read View,然后整个事务期间都在用这个 Read View,这样就保证了在事务期间读到的数据都是事务启动前的记录。"
"在启动时创建了 Read View,然后在事务期间读取数据的时候,在找到数据后,先会将该记录的 trx_id 和该事务的 Read View 里的字段做个比较"
******
1、如果记录的 trx_id 比该事务的 Read View 中的 creator_trx_id 要小,且不在 m_ids 列表里,
这意味着这条记录的事务早就在该事务前提交过了,所以该记录对该事务可见;
2、如果记录的 trx_id 比该事务的 Read View 中的 creator_trx_id 要大,且在 m_ids 列表里,
这意味着该事务读到的是和自己同时启动的另外一个事务修改的数据,这时就不应该读取这条记录,
而是沿着 undo log 链条往下找旧版本的记录,直到找到 trx_id 等于或者小于该事务 id 的第一条记录。
******
???不完整
读已提交:指一个事务提交之后,它做的变更才能被其他事务看到
隔离级别是在事务期间读到的数据都是已经提交了的数据
在每个 select 都会生成一个新的 Read View
事务期间的多次读取同一条数据,前后两次读的数据可能会出现不一致,因为可能这期间另外一个事务修改了该记录,并提交了事务。
1、
因为如果提交了事务,那么这条记录的 trx_id 就不会在 m_ids 列表里。
因此,事务 A 不能读取该记录,而是沿着 undo log 链条往下找。
隔离级别是在每个 select 都会生成一个新的 Read View,也意味着,事务期间的多次读取同一条数据,
前后两次读的数据可能会出现不一致,因为可能这期间另外一个事务修改了该记录,并提交了事务。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。