2023-03-23  阅读(48)
原文作者:一直不懂 原文地址:https://blog.csdn.net/shenchaohao12321/article/details/82798275

delete和 update操作可能并不直接删除原有的数据。例如,对上一小节所产生的表t执行如下的SQL语句:
DELETE FROM t WHERE a=1;

表t上列a有聚集索引,列b上有辅助索引。对于上述的 delete操作,通过前面关于undo log的介绍已经知道仅是将主键列等于1的记录delete flag设置为1,记录并没有被删除,即记录还是存在于B+树中。其次,对辅助索引上a等于1,b等于1的记录同样没有做任何处理,甚至没有产生 undo log。而真正删除这行记录的操作其实被“延时”了,最终在 purge操作中完成。

purge用于最终完成 delete和 update操作。这样设计是因为 InnoDB存储引擎支持MVCC,所以记录不能在事务提交时立即进行处理。这时其他事物可能正在引用这行,故 InnoDB存储引擎需要保存记录之前的版本。而是否可以删除该条记录通过 purge来进行判断。若该行记录已不被任何其他事务引用,那么就可以进行真正的 delete操作。可见, purge操作是清理之前的 delete和 update操作,将上述操作“最终”完成。而实际执行的操作为 delete操作,清理之前行记录的版本。

在前一个小节中已经介绍过,为了节省存储空间, InnoDB存储引擎的 undo log设计是这样的:一个页上允许多个事务的 undo log存在。虽然这不代表事务在全局过程中提交的顺序,但是后面的事务产生的 undo log总在最后。此外, InnoDB存储引擎还有个 history列表,它根据事务提交的顺序,将 undo log进行链接。如下面的一种情况:

在图7-17的例子中, history list表示按照事务提交的顺序将undo log进行组织。在InnoDB存储引擎的设计中,先提交的事务总在尾端。 undo page存放了 undo log,由于可以重用,因此一个 undo page中可能存放了多个不同事务的undo log。trx5的灰色阴影表示该 undo log还被其他事务引用。
在执行 purge的过程中, InnoDB存储引擎首先从 history list中找到第一个需要被清理的记录,这里为txl,清理之后 InnoDB存储引擎会在trx1的 undo log所在的页中继续寻找是否存在可以被清理的记录,这里会找到事务trx3,接着找到tx5,但是发现trx5被其他事务所引用而不能清理,故去再次去 history list中查找,发现这时最尾端的记录为trx2,接着找到trx2所在的页,然后依次再把事务trx6、trx4的记录进行清理。由于 undo page2中所有的页都被清理了,因此该 undo page可以被重用。

202303232333419301.png

InnoDB存储引擎这种先从 history list中找 undo log,然后再从 undo page中找undo log的设计模式是为了避免大量的随机读取操作,从而提高 purge的效率全局动态参数 innodb_purge_batch_size用来设置每次 purge操作需要清理的undo page数量。在InnoDB1.2之前,该参数的默认值为20。而从1.2版本开始,该参数的默认值为300。通常来说,该参数设置得越大,每次回收的 undo page也就越多,这样可供重用的 undo page就越多,减少了磁盘存储空间与分配的开销。不过,若该参数设置得太大,则每次需要 purge处理更多的 undo page,从而导致CPU和磁盘IO过于集中于对undo log的处理,使性能下降。因此对该参数的调整需要由有经验的DBA来操作,并且需要长期观察数据库的运行的状态。正如官方的 MySQL数据库手册所说的,普通用户不需要调整该参数。
当 InnoDB存储引擎的压力非常大时,并不能高效地进行 purge操作。那么 historyit的长度会变得越来越长。全局动态参数 innodb_max_purge_lag用来控制 history list的长度,若长度大于该参数时,其会“延缓”DML的操作。该参数默认值为0,表示不对history list做任何限制。当大于0时,就会延缓DML的操作,其延缓的算法为

    delay =((length(history_list)-innodb_max_purge_lag)*10)-5

delay的单位是毫秒。此外,需要特别注意的是, delay的对象是行,不是一个DML操作。例如当一个 update操作需要更新5行数据时,每行数据的操作都会被delay,故总的延时时间为5*delay。而 delay的统计会在每一次 purge操作完成后,重新进行计算。
InnoDB1.2版本引入了新的全局动态参数 innodb_max_purge_lag_delay,其用来控制delay的最大毫秒数。也就是当上述计算得到的 delay值大于该参数时,将 delay设置为innodb_max_purge_lag_delay,避免由于purge操作缓慢导致其他SQL线程出现无限制的等待。


Java 面试宝典是大明哥全力打造的 Java 精品面试题,它是一份靠谱、强大、详细、经典的 Java 后端面试宝典。它不仅仅只是一道道面试题,而是一套完整的 Java 知识体系,一套你 Java 知识点的扫盲贴。

它的内容包括:

  • 大厂真题:Java 面试宝典里面的题目都是最近几年的高频的大厂面试真题。
  • 原创内容:Java 面试宝典内容全部都是大明哥原创,内容全面且通俗易懂,回答部分可以直接作为面试回答内容。
  • 持续更新:一次购买,永久有效。大明哥会持续更新 3+ 年,累计更新 1000+,宝典会不断迭代更新,保证最新、最全面。
  • 覆盖全面:本宝典累计更新 1000+,从 Java 入门到 Java 架构的高频面试题,实现 360° 全覆盖。
  • 不止面试:内容包含面试题解析、内容详解、知识扩展,它不仅仅只是一份面试题,更是一套完整的 Java 知识体系。
  • 宝典详情:https://www.yuque.com/chenssy/sike-java/xvlo920axlp7sf4k
  • 宝典总览:https://www.yuque.com/chenssy/sike-java/yogsehzntzgp4ly1
  • 宝典进展:https://www.yuque.com/chenssy/sike-java/en9ned7loo47z5aw

目前 Java 面试宝典累计更新 400+ 道,总字数 42w+。大明哥还在持续更新中,下图是大明哥在 2024-12 月份的更新情况:

想了解详情的小伙伴,扫描下面二维码加大明哥微信【daming091】咨询

同时,大明哥也整理一套目前市面最常见的热点面试题。微信搜[大明哥聊 Java]或扫描下方二维码关注大明哥的原创公众号[大明哥聊 Java] ,回复【面试题】 即可免费领取。

阅读全文