我有一个在 Amazon MySQL/RDS 上运行的应用程序,需要维护 2 周的事务历史记录,之后可以(通常)清除数据。因为这不是一个硬性规则,所以我不能使用按天或按周进行分区来最有效地删除旧数据。
有几个表需要清除,其中许多表具有多个索引和外键约束(父/子)。
我正在删除块中的数据(一次 1000-3000 行)并在每个块之后提交。删除一定数量的块后,清除代码会暂停一段时间。
我的问题是这个过程在 10 到 15 分钟内非常有效,之后我开始看到删除数据块的延迟很大。我相信我的 SQL 尽可能高效。我可以在 MySQL 中的哪个位置更好地了解瓶颈?如果我停止我的代码并等待 15-20 分钟,删除性能会再恢复 10 分钟。
我会查看 InnoDB 重做日志文件的大小。
如果您用更改填充重做日志,则您描述的症状很典型,这会强制“同步刷新” - MySQL 会阻止进一步的更改,直到它可以通过从缓冲池中刷新脏页来释放部分重做日志。
RDS 过去默认使用非常小的重做日志文件大小,如果我记得的话,是 128M。多年来,他们不允许改变尺寸。但在过去的几年里,他们确实允许改变它。
以下是检查重做日志文件大小(以 MB 为单位)的方法:
要更改它,我认为您将使用 RDS 参数组 UI,然后重新启动您的 RDS 实例以应用更改。
为了监控这一点,我会观察写入重做日志的字节数:
每 10 分钟左右测量一次,然后绘制它。重做日志文件的大小是固定的,写入最终会到达末尾并回绕到文件的开头。它们不能覆盖代表缓冲池中脏页的日志中的更改,因此在它们接近这样做之前,MySQL 会强制同步刷新。
因此,您可以通过以均匀的间隔定期读取该变量来观察 Innodb_os_log_written 的速率。将此日志写入速率与日志文件大小进行比较(请记住,默认情况下您有两个重做日志文件,因此您的重做日志容量为 Innodb_log_file_size * 2)。
这允许您估计“我们每 N 分钟覆盖整个重做日志文件”。当删除速度很快时,这应该(大致)与您的 10-15 分钟时间段相关。
我想我记得这个计算有一些细微差别...... Innodb_os_log_written 可能包括一些覆盖,即在某些情况下,一些写入会向后寻找以重新写入块。因此,在某些情况下,数字可能不会相加。我不知道这里的详细信息。
无论如何,如果您增加重做日志的大小,InnoDB 早就知道能够更好地处理繁重的写入工作量。在允许的范围内增加它是很诱人的,但这对于您的大多数日常工作负载来说可能是多余的,并且写入流量较小。
也可以看看:
这取决于您如何执行
DELETEs
. 如果每次都DELETE
从表的开头扫描,越过不应该删除的行,那么它会变得越来越慢。我在这里讨论了几种进行有效删除的技术。
有些涉及记住你离开的地方,而不是重新开始。