MySQL InnoDB多版本机制(MVCC)

1.InnoDB多版本简介
InnoDB为一个多版本存储引擎:为了支持像并发和回滚等事务特性,InnoDB保存被修改数据行的旧版本信息。这些旧版本信息存储于叫做回滚段(沿用Oracle中类似的数据结构)表空间内。InnoDB使用回滚段中的信息来进行事务回滚所需的取消操作。其也使用这些就版本信息来构建旧版本数据行来完成一致性读。内部地,InnoDB为数据库中存储的每个数据行增加了三个域。一个6字节db_trx_id域表示insert或update该数据行的最后事务的事务鉴定符。同时,delete操作内部也被当做update处理,其中,该数据行的一个特定位被设置标示该行已被删除。每个数据行也包含一个叫做滚动指针的7字节db_roll_ptr域,滚动指针指向一个写入回滚段的取消日志记录。如果该数据行被修改了,该取消日志记录包含重建该数据行修改前内容的必要信息。一个6字节db_row_id域包含一个新数据行插入时单调递增的行ID。如果InnoDB自动产生了一个簇索引,则该索引包含该行ID值。否则,db_row_id列不会出现在任何索引中。
回滚段内的取消日志分为insert和update取消日志。insert取消日志仅在事务回滚时需要,一旦事务提交就会被抛弃。update取消日志也被用于一致性读,其仅在InnoDB不再为任何事务分配重构数据行较早版本而需要这些update取消日志信息的快照时,才会被抛弃。
定期提交事务,包括那些只发布一致性读的事务。否则,InnoDB不能抛弃update取消日志,从而导致回滚段变的很大,最终耗光表空间。
回滚段内的一条取消日志记录的物理大小通常比插入或修改的数据行要小。因此,可以用这个信息计算所需回滚端的空间。
InnoDB多版本机制中,当用SQL语句删除一个数据行时,物理上并非立即从库中将其删除。InnoDB仅在抛弃该删除操作写入的update取消日志记录时,才会物理上移除相应的数据行。这个移除操作叫做一个purge,其运行非常快,通常只需SQL语句执行删除时同等数量级的时间。
如果insert和delete按照同等速率小批量删除表中的数据行,purge线程可能会落后,且表会变的越来越大,因为所有的这些“死”数据行,并且会使所有的操作都磁盘受限和很慢。这种情况下,限制新数据行的操作,并通过调整innodb_max_purge_lag系统变量来为purge线程分配更多的资源。
2.多版本和二级索引
InnoDB多版本并发控制(MVCC)对待二级索引与簇索引不同。簇索引中的记录就地被修改,它们的隐藏系统列指向重构记录较早版本所需的取消日志项。不像簇索引记录,二级索引记录并不包含隐藏系统列,同时,它们也不是被就地修改。当二级索引记录被修改时,就的二级索引数据行被标示为删除,新的记录被插入,被标示为删除的记录最终被purge掉。当二级索引记录被标示为删除,或二级索引数据页被新事务修改时,InnoDB将在簇索引中查找该数据记录。簇索引中该记录的db_trx_id被检查,如果读事务初始化后该记录被修改,则从相应取消日志获取该记录的正确版本。
如果二级索引记录被标示为删除,或二级索引数据页被较新事务修改,则不会用到覆盖索引技术。而是从二级索引结构中获取数值,InnoDB从簇索引中查找该记录。
然而,如果索引条件下推(index condition pushdown,ICP)优化开启,部分where条件能通过索引字段评估,mysql服务器还是会将这部分where条件下推到存储引擎,然后,再通过该索引进行评估。如果没发现匹配记录,将避免簇索引查找。如果发现了匹配记录,甚至是表示为删除的记录,InnoDB将在簇索引中查找该记录。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章