NoteDeep
本页讨论:
  • 什么是InnoDB Multi-Versioning?为什么要有这个?
  • InnoDB Multi-Versioning的原理。
  • 注意事项

InnoDB Multi-Versioning

MVCC是Multi Version Concurrency Control的简称,代表多版本并发控制。
InnoDB是一个多版本的存储引擎:它保留更改之前旧版本的数据行的信息,以支持事务功能,如并发和回滚。
直观的看:

主要是为了实现
  • 实现隔离级别REPEATABLE READ
  • Consistent nonlocking read(默认读不加锁,一致性非锁定读), 提升并发能力。
  • 还用于事务的回滚。
最原生的锁,锁住一个资源后会禁止其他任何线程访问同一个资源。但是很多应用的一个特点都是读多写少的场景,很多数据的读取次数远大于修改的次数,而读取数据间互相排斥显得不是很必要。所以就使用了一种读写锁的方法,读锁和读锁之间不互斥,而写锁和写锁、读锁都互斥。这样就很大提升了系统的并发能力。之后人们发现并发读还是不够,又提出了能不能让读写之间也不冲突的方法,就是读取数据时通过一种类似快照的方式将数据保存下来,这样读锁就和写锁不冲突了,不同的事务session会看到自己特定版本的数据。当然快照是一种概念模型,不同的数据库可能用不同的方式来实现这种功能。 之后的讨论默认均以REPEATABLE READ作为隔离级别。

InnoDB Multi-Versioning的原理。


在内部,InnoDB向数据库中的每行数据添加三个字段。
6字节 DB_TRX_ID 字段指示插入或更新行的最后一个事务的事务标识符。
此外,删除在内部被处理为更新,该行数据中的特殊位被标记为已删除。
每行还包含一个称为roll pointer的7字节DB_ROLL_PTR字段。roll pointer指向一个回滚的日志。如果行已更新,则回滚日志记录会包含回滚该行内容所需的信息。

如图所示:


6字节DB_ROW_ID字段包含随插入新行而单调递增的行ID。如果InnoDB自动生成聚簇索引,则索引包含行ID值。否则,DB_ROW_ID列不会显示在任何索引中。

新增一个事务时事务id会增加,trx_id能够表示事务开始的先后顺序。
Undo log分为Insert和Update两种,delete可以看做是一种特殊的update,即在记录上修改删除标记。 update undo log记录了数据之前的数据信息,通过这些信息可以还原到之前版本的状态。
回滚日志分为Insert undo log和update undo log。只有当一个事务需要回滚时,才可能使用到Insert undo log。只要事务提交后,Insert undo log就可以被删除。
update undo log也用于一致性读取,但是只有当前InnoDB快照中,没有正在进行的事务之后,它们才能被丢弃,因为可能需要update undo log中的信息来构建较早版本的数据库行。


注意事项

定期提交您的事务。否则,InnoDB不能从更新回滚日志中丢弃数据,需要保存的日志太多,并且 rollback segment回滚段可能会增长太大,从而填满tablespace表空间

删除行也会写更新回滚日志,执行SQL语句删除行时,不会立即从磁盘上删除一行。仅在丢弃了该更新回滚日志时,才会物理删除相应行及其索引记录。这个删除操作被称为purge清除,它是相当快的,与执行删除SQL语句的耗时相同。

如果您在表中以相同的速率插入和删除小批量的行,则清除线程会落后,并且由于所有“死”行,表会变得越来越大,从而受到磁盘限制而变慢。在这种情况下,调节新行操作,可以调整innodb_max_purge_lag系统变量,mysql将会分配更多资源给清除线程。

评论列表

    InnoDB Multi-Versioning
    InnoDB Multi-Versioning的原理。