MVCC(数据库多版本并发控制)
前面的文章说到数据库的事务问题,在innodb引擎四个隔离级别(读未提交RU;读已提交RC;可重复读RR;可串行化Serializable
)中,而MVCC只适用于RC和RR。
一、什么是MVCC
Multi-Version Concurrency Control,就是在事务执行过程中加入“版本”这个概念、MVCC的实现,通过保存数据在某个时间点的快照来实现的。
1、MVCC优缺点
MVCC在大多数情况下代替了行锁
,实现了对读的非阻塞
,读不加锁
,读写不冲突
。缺点是每行记录都需要_额外的存储空间_
,需要做更多的行维护和检查工作。
innodb 在事务上离不开undo log,那什么是undo log?
在数据库中有三种日志形式,binlog/redo log /undo log。
binlog
二进制日志是server层
的,主要是左主从复制,时间点恢复
使用,保存的是逻辑日志->执行的sql语句。
redo log
重做日志是InnoDB存储引擎层
的,用来保证事务安全,
保存的是物理日志->数据。
undo log
回滚日志保存了事务发生之前的数据的一个版本
,可以用于回滚
,同时可以提供多版本并发控制下的读(MVCC)
,也即非锁定读。保存的是逻辑日志->数据前一个版本。
其中,redo log通常是物理日志,记录的是数据页的物理修改。undo用来回滚行记录到某个版本。undo log一般是逻辑日志,根据每行记录进行记录。
通过以上知识点可以大体理解为:MVCC通过undo log 日志形式在事务中标记一个时间点形成快照,通过这个时间点的日志可以对事务进行回滚操作。
在不考虑redo log 的情况下利用undo log工作的简化过程为:
序号 | 动作 |
---|---|
1 | 开始事务 |
2 | 记录数据行数据快照到undo log |
3 | 更新数据 |
4 | 将undo log写到磁盘 |
5 | 将数据写到磁盘 |
6 | 提交事务 |
1)为了保证数据的持久性数据要在事务提交之前持久化
2)undo log的持久化必须在在数据持久化之前,这样才能保证系统崩溃时,可以用undo log来回滚事务
2、InnoDB存储引擎是如何记录事务操作的呢?
InnoDB存储引擎在数据库每行数据的后面添加了三个字段。事务id+回滚指针+自增id
6字节的事务ID
(DB_TRX_ID
)字段: 用来标识最近一次对本行记录做修改
(insertupdate)的事务的标识符, 即最后一次修改(insertupdate)本行记录的事务id。至于delete操作,在innodb看来也不过是一次update操作,更新行中的一个特殊位将行表示为deleted, 并非真正删除
。
7字节的回滚指针
(DB_ROLL_PTR
)字段: 指写入回滚段(rollback segment)的 undo log
record (撤销日志记录记录)。如果一行记录被更新, 则 undo log
record 包含 ‘重建该行记录被更新之前内容’ 所必须的信息。
6字节的DB_ROW_ID
字段: 包含一个随着新行插入而单调递增的行ID, 行标识。(当由innodb自动产生聚集索引时,聚集索引会包括这个行ID的值,否则这个行ID不会出现在任何索引中。
结合聚簇索引的相关知识点, 我的理解是, 如果我们的表中没有主键或合适的唯一索引, 也就是无法生成聚簇索引的时候, InnoDB会帮我们自动生成聚集索引, 但聚簇索引会使用DB_ROW_ID的值来作为主键; 如果我们有自己的主键或者合适的唯一索引, 那么聚簇索引中也就不会包含 DB_ROW_ID
了 。
MVCC(数据库多版本并发控制)