Innodb MVCC工作原理

北慕城南 提交于 2020-03-08 16:52:27

《MySQL》高性能的说法:

为何需要MVCC

        对于事务型的存储引擎实现,仅仅依赖锁是不够的,还需要MVCC(Multiversion Concurrency Control )的帮助,可以简单的将MVCC理解成为一个row lock的一个变种,只是在必要的时候加行锁。

InnoDB的MVCC实现方式

        每个事物存储引擎的MVCC实现方式是不一样的,InnoDB的MVCC简单来讲是通过给表添加两列隐藏列。

        一列(创建列)存储行的insert(如果行不存在)时间或者update(如果行已存在)时间,一列存储行的删除时间,当然,这里的时间并非我们所说的时分秒,而是系统版本号(system version number),列存储的SVN是事物开始时刻的SVN,每开始一个新的事物,SVN号递增。

MVCC只有在隔离级别是READ COMMITED(Oracle默认)和REPEATABLE READ(MySQL默认)两个隔离级别下工作。

现在讨论在REPEATABLE READ下的MVCC实现:

SELECT

        a. Innodb查找SVN小于等于当前事物的SVN的行,如果是小于,说明行之前就已经存在,如果是等于,说明这行是事物本身修改过的.

        b.行的删除时间列要么为空(说明该行未被删除)要么删除时间列的SVN大于当前事物的SVN(表示行是在事物开始之后被删除的).

只有记录满足以上两条,才会被select语句返回!


Insert

        插入之后以当前事物的SVN号更新创建列

Delete

        删除之后,用当前SVN更新删除列

Update

        更新创建列为当前SVN,同时更新删除列为update之前的创建列的SVN值

这样设计的优点是大部分的读操作都不用加锁了,使数据库操作简单,性能好,不足之处是增加了存储开销,需要额外的维护工作

查阅5.5的官方文档,关于MVCC的介绍是这样的:

InnoDB的MVCC是通过保存旧版本的修改信息来实现事物的并发控制和回滚。这些信息以一种数据结构的形式保存在表空间中,这种数据结构就是“rollback segment”回滚段可以提供两项功能:回滚,一致性读。

与MVCC相关的元素

DB_TRX_ID:占6字节,用来标识最近一次修改(insert|update)行的事物的标识符,至于delete操作,在innodb看来也不过是一次update操作,更新行中的一个特殊位将行表示为deleted。并非真正删除。

DB_ROLL_PTR:占用7个字节,滚动指针指向回滚段中的对应回滚日志记录,如何update一行,那么改行旧的信息就会被保存到指针所指向的回滚段中。

DB_ROW_ID:该值随行数的增多而增加,如果是cluster index,会包含这列,其他索引则不会有这列。

对于回滚段的管理:

        Insert Logs:当事物被提交时,所保存的insert 回滚记录就可以被删除

        Update Logs:这个日志不仅仅在rollback时需要,在一致性读也需要,所以不能随便删除,只有当数据库所使用的快照中不涉及该日志记录,对应的回滚日志才可以删除。


回滚段的管理指导:

经常将一些事务提交,包括哪些只发出一致性读的事务,否则InnoDB无法删除回滚段中的 undo update logs,这将导致回滚段增长过快直到填满表空间。

在InnoDB中,发出Delete语句之后,改行并不会立刻被物理的从数据库中删除,只有当对应的行update undo logs被删除之后,才会被物理的删除(purge)purge操作很快,时间等于delete所用时间。

有个问题:在频繁的进行小规模的插入和删除操作,purge线程将会滞后。因为无法删除这些被标记为deleted的行,这会导致表越来越大,导致磁盘瓶颈,性能下降。

解决办法:限制新行的操作,分配更多的资源给purge线程。涉及参数innodb_max_purge_lag

当purge_lags表示有多少经过delete或者update操作被标记为deleted的行,没有被purge,如果该值超过了innodb_max_purge_lag值,则delete和insert,update操作将会被挂起。


The InnoDB transaction system maintains a list of transactions that have index records delete-marked by UPDATEor DELETE operations. The length of this list represents the purge_lag value. When purge_lag exceedsinnodb_max_purge_lag, each INSERTUPDATE, and DELETE operation is delayed by ((purge_lag/innodb_max_purge_lag)×10)–5 milliseconds. The delay is computed in the beginning of a purge batch, every ten seconds. The operations are not delayed if purge cannot run because of an old consistent readview that could see the rows to be purged.

root@localhost>show engine innodb status\G
------------
TRANSACTIONS
------------
Trx id counter 9652
Purge done for trx's n:o < 7965 undo n:o < 0 state: running but idle
History list length 17
LIST OF TRANSACTIONS FOR EACH SESSION:
---TRANSACTION 0, not started
MySQL thread id 13, OS thread handle 0x8effdb70, query id 361 localhost root init
show engine innodb status




易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!