解决事务隔离产生问题的MVCC

469 阅读3分钟

​​本文源自Recently祝祝,创自Recently祝祝。转载请标注出处。

什么事MVCC ?

MVCC称为:多版本并发控制,数据多版本并发控制,Multi Version Concurrency Control,也可以称为MCC,反正我最先知道他就是被称为MCC,因为当时我了解他的时候是这样的MultiVersion Concurrency Control。

MVCC应用在那些数据库的领域?

MYISAM,非聚集索引不存在事务这个概念,更不用说MVCC了,只支持表锁。

MVCC只能用于INNODB聚集索引表下的,Reapeable read 和 Read committed 机制。

MVCC有什么作用?

避免了直接使用锁,大家都知道,使用锁固然是一种很好的方法,保证机制的安全性,但是使用锁的同时大大减低了程序运行的效率,MVCC就是一种,不加任何锁,却达到了锁的目的的一种良好的机制,同时保证了业务安全与效率的平衡性。 MVCC:通过一定机制生成一个数据请求点的一致性数据快照(Snapshot) ,通过 这个快照提供一定级别的一致性读取,类似于多个版本并发执行

MVCC的工作原理?

特点:只适用于处理“读写”和“写读”的并发事件

MVCC的组成?

隐藏列:

DB_ID -> 系统ID(不可重复,在Oracle中称为伪列) DB_TRX_ID -> 事务ID(可以为空) DB_ROLL_PT -> 回滚指针

开启事务不会产生事务ID(事务编号),只有在修改数据时会出现事务ID,查询的事务ID与修改的事务ID不同,查询的事务ID大得多,一遍情况下回产生两个事务ID,一个是查询,一个是修改的 修改数据:添加insert,删除delect,更新update

日志:

undo_log -> 回滚数据 : 分为两种: insert_undo_log update_undo_log

redo_log-->恢复数据 “日志先行”(Write-Ahead Logging),在事务开启后,在事务提交之前,会将数据先写入存储引擎的日志缓存中。事务提交之后,会把数据刷新到磁盘持久化。 但是在数据库崩了的时候,就可以很有效的使用redo log 进行数据恢复了。

事务链(版本链):

  1. 修改和删除产生事务链
  2. 添加不写入事务链
  3. 一条数据产生一个事务链
  4. 删除和修改在同一张表上
  5. 除了查询不计其他都计入
  6. select请求是不会产生版本链的增加的,只有insert update delete有
  7. 还未提交的数据事务ID在数组内,不加入版本链中

ReadView:

组成 活动事务ID 数组 最小事务ID 下次事务ID

算法

在这里插入图片描述

规则 READ COMMITTED -> 每次事务查询都会产生最新ReadView REPEATABLE READ -> 在事务结束之前只保留第一次查询时产生的ReadView

提交读在MVCC中的工作模式:READ COMMITTED

每次事务查询都会产生一个新的ReadView

可重复读在MVCC中的工作模式:REAPETABLE READ

事务结束之前只保留了一次查询是产生的ReadView

解释不可重复读

在这里插入图片描述

	事务A 								   事务B
   1begin;								BEGIN;
   2insert INTO tab(tname,tmoney) VALUES('recently祝祝',80000);(查看事务ID)-- 9322      
   3commit;							
   4begin;								BEGIN;
   5update tab SET tname='a' WHERE id=8;(查看事务ID)-- 9327 	
   6SELECT id,tname,tmoney  FROM tab WHERE id=8;-- 83960
   7:									    SELECT tname,tmoney  FROM tab;-- 83960 -- 查不到
   8:COMMIT;								
   9:										SELECT id,tname,tmoney  FROM tab WHERE id=8;-- 查不到
   10commit

在这里插入图片描述

解释幻读: 在这里插入图片描述

-- REAPETABLE READ -- MySQL中默认的隔离级别
-- 幻读的原因
	事务A 									事务B
   1begin;								BEGIN;
   2insert INTO tab(tname,tmoney) VALUES('shimmer',8000);(查看事务ID)-- 9337   
   3SELECT id,tname,tmoney  FROM tab WHERE id=9;-- 查不到
   4commit5SELECT id,tname,tmoney  FROM tab WHERE id=9;-- 查不到数据
   6UPDATE tab SET tname='a' WHERE id=9;(查看事务ID)-- 9338  
   6SELECT id,tname,tmoney  FROM tab WHERE id=9; -- 查到数据
   7:										COMMIT;								

在这里插入图片描述

请添加图片描述

请添加图片描述

查看事务ID:

USE information_schema;
SELECT * FROM innodb_trx;