本文源自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 进行数据恢复了。
事务链(版本链):
- 修改和删除产生事务链
- 添加不写入事务链
- 一条数据产生一个事务链
- 删除和修改在同一张表上
- 除了查询不计其他都计入
- select请求是不会产生版本链的增加的,只有insert update delete有
- 还未提交的数据事务ID在数组内,不加入版本链中
ReadView:
组成 活动事务ID 数组 最小事务ID 下次事务ID
算法
规则 READ COMMITTED -> 每次事务查询都会产生最新ReadView REPEATABLE READ -> 在事务结束之前只保留第一次查询时产生的ReadView
提交读在MVCC中的工作模式:READ COMMITTED
每次事务查询都会产生一个新的ReadView
可重复读在MVCC中的工作模式:REAPETABLE READ
事务结束之前只保留了一次查询是产生的ReadView
解释不可重复读
事务A 事务B
1:begin; BEGIN;
2:insert INTO tab(tname,tmoney) VALUES('recently祝祝',80000);(查看事务ID)-- 9322
3:commit;
4:begin; BEGIN;
5:update tab SET tname='a' WHERE id=8;(查看事务ID)-- 9327
6: SELECT 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;-- 查不到
10: commit;
解释幻读:
-- REAPETABLE READ -- MySQL中默认的隔离级别
-- 幻读的原因
事务A 事务B
1:begin; BEGIN;
2:insert INTO tab(tname,tmoney) VALUES('shimmer',8000);(查看事务ID)-- 9337
3: SELECT id,tname,tmoney FROM tab WHERE id=9;-- 查不到
4:commit;
5: SELECT id,tname,tmoney FROM tab WHERE id=9;-- 查不到数据
6: UPDATE tab SET tname='a' WHERE id=9;(查看事务ID)-- 9338
6: SELECT id,tname,tmoney FROM tab WHERE id=9; -- 查到数据
7: COMMIT;
查看事务ID:
USE information_schema;
SELECT * FROM innodb_trx;