MVCC:
从我们的直观理解上来看,要实现数据库的并发访问控制,最简单的做法就是加锁访问,即读的时候不能写(允许多个线程同时读,即共享锁S锁),写的时候不能读(一次最多只能有一个线程对同一份数据进行写操作,即排它锁X锁)。这样的加锁访问,其实并不算是真正的并发。因为它最终实现的是读写串行化,这样数据库的读写性能将会被大大降低。加锁访问其实就是和MVCC相对的LBCC,即基于锁的并发控制,是四种隔离级别中级别最高的Serialize隔离级别。
MVCC(多版本并发控制) 则是为了实现数据库的并发控制而设计的一种协议。它主要是为RR事务隔离级别做的。它的最大好处便是,读不加锁,读写不冲突。在MVCC中,读操作可以分成两类,快照读(Snapshot read)和当前读(current read)。
快照读:读取的是记录的可见版本(可能是历史版本,即最新的数据可能正在被当前执行的事务并发修改),不会对返回的记录加锁
当前读:读取的是记录的最新版本,并且会对返回的记录加锁,保证其他事务不会并发修改这条记录。
InnoDB中实现MVCC:
InnoDB的MVCC实现,是通过保存数据在某个时间点的快照来实现的。一个事务,不管其执行多长时间,其内部看到的数据是一致的。也就是事务在执行的过程中不会相互影响。
MVCC在每行记录后面保存几个隐藏的列:DATA_TRX_ID,DATA_ROLL_PTR,DB_ROW_ID,DELETE BIT
DATA_TRX_ID:6字节 标记了最新更新这条行记录的transaction id,每处理一个事务,其值自动+1(删除视为更新,将其标记为已删除)
DATA_ROLL_PTR:7字节 指向当前记录项的rollback segment的undo log记录(写入回滚段的撤消日志记录),找之前版本的数据就是通过这个指针(若行已更新,则撤消日志记录包含在更新行之前重建行内容所需的信息)
DB_ROW_ID:6字节 行标识
DELETE BIT:位用于标识该记录是否被删除,这里的不是真正的删除数据,而是标志出来的删除。真正意义的删除是在commit的时候
undolog:
Undo日志记录某数据被修改前的值
不考虑redo log 的情况下undo log的工作过程redolog:
用于在实例故障恢复时,继续那些已经commit但数据尚未完全回写到磁盘的事务
大致的执行过程:begin->用排他锁锁定该行->记录redo log->记录undo log->修改当前行的值,写事务编号,回滚指针指向undo log中的修改前的行
示例(RR隔离级别):
SELECT
1 InnoDB只查找版本早于当前事务版本的数据行(也就是数据行的版本必须小于等于事务的版本),这确保当前事务读取的行都是事务之前已经存在的,或者是由当前事务创建或修改的行
2 行删除操作的版本一定是未定义的或者大于当前事务的版本号,确定了当前事务开始之前,行没有被删除
INSERT
InnoDB为每个新增行记录当前系统版本号作为行版本号。
DELETE
InnoDB为每个删除行的记录当前系统版本号作为行的删除标识。
UPDATE
变为insert和delete操作的组合,insert的行保存当前版本号为行版本号,delete则保存当前版本号到原来的行作为删除标识。
由于旧数据并不真正的删除,所以必须对这些数据进行清理,innodb会开启一个后台线程执行清理工作,具体的规则是将删除版本号小于当前系统版本的行删除,这个过程叫做purge。
网友评论