作者 | 流火星
本篇文章给大家带来的是 【Mysql-InnoDB系列】- InnoDB的ACID模型
InnoDB的ACID
ACID模型是一些列数据库设计原则的集合,旨在提升可靠性,这对商业数据和关键应用是至关重要的。MySQL包含诸多组件,例如严格遵循ACID模型的InnoDB存储引擎,以保障数据不会因为软件崩溃和硬件故障,而导致数据损坏和结果失真。当依赖ACID一致性特性时,你不需要自己再造轮子来进行校验和故障恢复机制。如果你有额外的软件保护措施,超可靠的硬件,或者应用可容忍小部分的数据丢失或不一致,你可以调整MySQL配置,通过牺牲一些ACID的可靠性来获得更高的性能或吞吐量。
InnoDB的多版本(MVCC)
InnoDB是多版本支持的存储引擎:它为发生变化的行保存了旧版本信息,来支持并发和回滚的事务特性。信息存储在表空间,一个称为回滚段-roolback segment(在Oracle使用类似的数据结构之后)的数据结构。InnoDB使用回滚段中的信息来执行一个事务回滚之后的undo操作。这个信息也同样被用来在一致读场景下建立行数据的早期版本。
InnoDB为在数据库中存储的每行数据增加了3个字段。
1、一个6比特的DB_TRX_ID字段,代表上一个事务的插入/更新行操作的事务标识符。删除在内部被视为更新,行中的特殊位被设置为将其标记为已删除。
2、一个7比特的DB_ROLL_PTR字段,称为回滚指针。回滚指针指向写入回滚段的一条undo日志记录。如果行被更新,那么包含这个信息的undo日志记录,在更新前必须重新生成行记录。
3、一个6比特的DB_ROW_ID字段,插入新行时单调增加的行ID。如果InnoDB自动生成聚集索引,则索引包含行ID值。否则,该列不会出现在任何索引中。
回滚段中的undo日志分为插入undo日志和更新undo日志。插入undo日志只在事务回滚时需要,并能够在事务提交时尽快丢弃。而更新undo日志在一致读中也会使用,只有在不存在InnoDB为其分配了快照的事务之后,才能丢弃这些快照。在一致读取中,该快照可能需要更新撤消日志中的信息来构建数据库行的早期版本。
定期提交事务,包括那些只发出一致读取的事务。否则,InnoDB无法从update undo日志中丢弃数据,并且回滚段可能会变的过大,占满你的表空间。
回滚段中undo log记录的物理大小,通常小于相应的插入行或更新行。你可以使用这个信息来计算回滚段所需的空间。
在InnoDB的多版本模式中,当你通过sql语句删除一个记录行时,它并不会马上从数据库中被物理删除。InnoDB只有在丢弃 为删除写入的update undo日志记录时,才会物理删除相关的行和索引记录。这个删除操作称之为purge(清理),并且这个操作执行很快,通常是与执行删除的sql语句相同数量级的耗时。
如果以大约相同的速率小批量地插入和删除表中的行,清理线程可能会开始落后,表也会由于所有”死“行记录的堆积变的越来越大,使得任何事情都受磁盘限制并且非常缓慢。在这种情况下,可以通过调整innodb_max_purge_lag系统变量来限制新行操作,并分配更多资源给清理线程。
多版本和二级索引
InnoDB多版本控制(MVCC)在处理二级索引和聚簇索引时有所不同。聚簇索引中的记录是就地更新,它们的隐藏系统字段指向undo log,从中可以重建记录的早期版本。与聚簇索引记录不同,二级索引记录并不包含隐藏系统字段,并且它们也不会就地更新。
当一个二级索引列被更新时,旧的二级索引记录会被标记删除,新的记录被插入,并且已经标记删除的记录最终会被清理。当一个二级索引记录被标记删除,或者二级索引页被一个新的事务更新时,InnoDB会在聚簇索引中查找数据库记录。在聚簇索引中,记录的DB_TRX_ID会被检查,如果记录在读事务开始之后被修改,那么记录的正确版本会从undo log中找回。
如果二级索引记录被标记删除,或二级索引页被更新的事务更改,那么不会使用覆盖索引技术。InnoDB会从聚簇索引中查找记录,而不是从索引结构中返回值。
然而,如果开启了索引条件下推(ICP)优化项,并且部分WHERE条件评估后可以只使用索引覆盖的字段,MySQL服务器仍然将WHERE条件的这一部分向下推送到存储引擎,在那里使用索引对其进行评估。如果没有找到匹配记录,就会避免聚簇索引查找。如果找到了匹配记录,哪怕是在标记为删除的记录中,InnoDB也会在聚簇索引中查找记录。
感谢各位阅读 我们的 InnoDB的ACID模型 的介绍结束
希望大家有耐心的进行阅读~