有你,世界才更有趣!

MVCC(数据库多版本并发控制)

前面的文章说到数据库的事务问题,在innodb引擎四个隔离级别(读未提交RU;读已提交RC;可重复读RR;可串行化Serializable)中,而MVCC只适用于RC和RR。

什么是MVCC?

Multi-Version Concurrency Control,就是在事务执行过程中加入“版本”这个概念、MVCC的实现,通过保存数据在某个时间点的快照来实现的。

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来回滚事务

InnoDB存储引擎是如何记录事务操作的呢?

InnoDB存储引擎在数据库每行数据的后面添加了三个字段。事务id+回滚指针+自增id

6字节的事务ID(DB_TRX_ID)字段: 用来标识最近一次对本行记录做修改(insert|update)的事务的标识符, 即最后一次修改(insert|update)本行记录的事务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 了 。
点赞

发表评论

电子邮件地址不会被公开。 必填项已用*标注