MySQL的Dynamic InnoDB重做日志

从8.0.30开始,您可以在线修改InnoDB重做日志容量。重做日志容量不足会造成问题并导致性能问题。

但是,也不建议过大重做日志。重做日志文件会占用磁盘空间,并在重新启动(innodb_fast_shutdown=1)或突然崩溃时增加恢复时间。当innodb_fast_shutdown=0时,它也会减慢关机速度。

这意味着,如果您想增加或减少InnoDB重做日志文件的大小,现在不需要重新启动MySQL。事实上,我们不再讨论文件大小,而是讨论容量!DBA不再需要像以前那样为重做日志指定任何文件大小和/或文件量。

一种新的重做日志架构

新的重做日志大小由一个变量定义:innodb_redo_log_capacity(以字节为单位)。默认值为100MB。

例如,您可以使用以下SQL语句将重做日志容量更改为200MB:

set global innodb_redo_log_capacity=200*1024*1024;

InnoDB在MySQL的datadir中的一个新的专用文件夹中创建32个重做日志文件:#InnoDB_redo。

在该目录中,您将能够找到两种类型的文件:

  • #ib_redoXXX(其中XXX是file_id,序列号):这些是活动的重做日志文件

  • #ib_redoXXX_tmp:这些是备用重做日志文件

InnoDB尝试在这里维护大约32个文件,因此不需要等待很长时间,其中一个文件就不再需要了,就像您只有两个大文件一样。这样,当您想调整它们的大小时,它可以一个接一个地回收它们。

这就是它的表现方式:

  • checkpoint_lsn(Innodb_redo_log_checkpoint_lsn):一个lsn点,在此点之前,页面的所有更改都保证已经写入并同步回表空间文件——基本上,重做日志中仍然需要的部分从这里开始。

  • current_lsn(Innodb_redo_log_current_ lsn):重做日志中最后写入的位置。该写入仍然可以在MySQL进程缓冲区中缓冲。

  • flush_to_disk_lsn(Innodb_redo_log_flush u to_ disk_ lsn):重做日志中Innodb已刷新到磁盘的最后一个位置。

现在,当我们到达第31个文件(90%)的末尾时,日志文件调控器将执行一些清理,一些不再需要的活动文件将成为新的备用文件:

当后台线程无法从左侧删除日志文件以将其放到右侧时,用户事务将被卡住,等待重做缓冲区写入磁盘。DBA在错误日志中得到警告,通知他们增加InnoDB重做日志容量:

[Warning] [MY-013865] [InnoDB] Redo log writer is waiting for a new redo log file.
 Consider increasing innodb_redo_log_capacity.

检查点

让我们回顾一下重做日志的作用。您可能已经知道,每次在InnoDB中更改数据时,包含数据的页面都会在内存(InnoDB缓冲池中)中进行修改。页面被标记为脏页面。万一突然崩溃,我们不能丢失所有这些更改…但内存中的数据已经消失了!这就是为什么页面的差异数据也会写入重做日志(默认情况下会刷新到磁盘)。在InnoDB恢复的情况下,这些日志中的数据将是只读的。在此过程中,将使用修改的数据重建修改的页面。

InnoDB将这些脏页从缓冲池(内存)一步一步地小批量刷新到表空间(磁盘)。这种操作称为模糊检查点。

一旦页面写入磁盘上的数据文件(InnoDB表空间),则不再需要重做日志中的相应条目。InnoDB将数据写入磁盘的位置是InnoDB_redo_log_checkpoint_lsn的值。

InnoDB检查点是自适应的。这意味着考虑到检查点年龄(log_lsn_checkpoint_age),InnoDB将决定更少或更积极地刷新。

本手册有一节介绍自适应冲洗。

对于信息,log_lsn_checkpoint_age和inndob_redo_log_logical_size几乎相等:

返回到lsn检查点年龄和重做日志容量阈值:

  • 逻辑容量的软限制:为了避免死锁,InnoDB不允许用户事务耗尽整个InnoDB_redo_log_capacity,而是将其保持在软逻辑容量以下,大约为其30/32。当超过此限制时,所有用户线程都将暂停,并向error_log发送消息

  • 逻辑容量的硬限制:永远不会超过此限制。如果在达到限制时等待1秒后没有回收空间,则会尽可能多地写入日志,否则会导致InnoDB崩溃!

  • 异步刷新点(log_max_modified_age_async):允许写入,但页面刷新将逐渐增加,以达到下一个阈值。这将导致性能下降。在代码中,异步刷新点可以称为adaptive_flush_min_age。这是软逻辑容量的7/8。

然而,在实践中,自适应刷新似乎已经在innodb_adaptive_flushing_lwm(默认为软逻辑容量的10%)开始,并在异步刷新点的82%处达到最大允许IO容量。

  • 同步刷新点(log_max_modified_age_sync):此时,检查点将请求页面清理器刷新尽可能多的脏页面,以使检查点年龄低于此阈值,并将同步等待。这是一场糟糕的表演。这也称为adaptive_flush_max_age。这是软逻辑容量的15/16。

  • aggressive_checkpoint_min_age:这表示31/32的软逻辑容量。当达到这一点时,InnoDB已经要求InnoDB全速刷新缓冲池中的脏页。在尝试更新检查点lsn之间,检查点不会休眠1秒——相反,它将尽可能频繁地请求同步检查点,并在之后尽快将checkpoint_lsn值更新到重做日志头中。这样做是为了能够更快地回收空间。由于我们已经处于最高速度,这不会给页面清理器增加任何压力。

仪器

新的重做日志在表innodb_Redo_Log_files中的Performance_Schema中插入:

这意味着有5个活动重做日志文件和27(32-5)个备用文件(_tmp):

所有文件也在Performance_Schema的文件实例表(file_instances和file_summary_by_instance)中插入:

通常,有状态变量和InnoDB度量条目提供有关“flushpointing”操作的信息:

蛇的比喻

新的重做日志架构可以被视为一条蛇(为了确保InnoDB的耐久性,仍然需要有用的重做记录信息),横穿笼子(重做日志文件)。这些笼子是连续连接在一起的,这样蛇就可以继续前进。当蛇到达右边倒数第二个笼子的末端时,InnoDB将不再需要的笼子从左边移到右边。笼子的数量始终为32个(除非有非常特殊的情况)。

蛇的大小可以变长或缩小。当InnoDB将脏页从缓冲池刷新到数据文件时,不需要重做日志信息,snake的尾部(checkpoint_lsn)也会向右移动。蛇尾巴左边剩下的笼子里装着蛇的旧皮。

一些例子

让我们看看一些输出,看看如何说明这一点。

示例1–空载

在上面的示例中,我们可以看到current_lsn、checkpoint_lsn和flushed_to_disk_lsn具有相同的值。它们都在最后一个活动日志(id 10844)中。事实上,目前没有交易。

snake处于其最小大小(Innodb_redo_log_logical_size):512字节。检查点年龄为0:

示例2–负载

我们在这里看到,蛇更大,仍然有足够的空间。如果需要(当蛇到达倒数第二个笼子的90%时,包含蛇的旧皮的笼子将被重新用作新的备用笼子。

重做日志使用者

正如我已经解释的,InnoDB重做日志仅在InnoDB恢复过程中读取(消耗)。但这不是事实。正如本博客文章所解释的,一些进程也可以读取重做日志文件。

以下是潜在“消费者”列表:

1.InnoDB恢复。

2.使用UDF innodb_redo_log_consumer_register()的线程。例如,MEB(MySQL企业备份)就使用这种方法。如果使用不当,可能会导致相当大的性能问题,因此需要BACKUP_ADMIN权限。

3.克隆人的档案管理员。

这些过程会减慢重做日志文件的重复使用(转换为备用重做日志)。这意味着最左边的保持架不能向右移动,因为它仍在使用。

这些消费者必须通过共享其当前lsn向InnoDB提供其进展。

在InnoDB恢复(1)的情况下,通过查看当前检查点lsn,我们知道最需要的lsn是什么。这意味着“检查点线程”是消费者之一,并且它总是被注册的。

对于(2),消费者需要使用UDF inndob_redo_log_consumer_advance(lsn)手动向前移动光标。需要结束会话以注销消费者。

最后,当克隆(3)正在进行时,我们注册克隆的消费者,克隆知道如何推进其当前lsn(使用API)。

一些有用的查询

以下是一些有趣的查询及其输出。其中大多数使用InnoDB度量表。

要启用所有功能,需要运行以下SQL语句:

设置全局innodb_monitor_enable=all;

您还可以指定要启用的选项。你必须这样一个一个地做:

设置全局innodb_monitor_enable=‘log_lsn_checkpoint_age’;

重做日志活动文件概述

获取检查点年龄

检查点年龄是当前LSN值与最后一个检查点LSN值的差值。如前所述,检查点时间应该几乎等于InnoDB重做日志逻辑大小的值。

这是我用来显示它的查询(我们之前已经看到过该查询):

请注意,必须启用InnoDB度量才能获得一致的结果。

如果不启用这些度量,您可能会得到以下奇怪的无效结果:

+------------------------+------------------------------+
| log_lsn_checkpoint_age | innodb_redo_log_logical_size |
+------------------------+------------------------------+
| 5976089 (5.70 MiB) | 512 ( 512 bytes) |
+------------------------+------------------------------+

这是不正确的,log_lsn_checkpoint_age应该是0!您可以通过以下查询验证所需的度量是否已启用:

SELECT status FROM INFORMATION_SCHEMA.INNODB_METRICS
WHERE NAME like 'log_lsn_checkpoint_age';
+----------+
| status |
+----------+
| disabled |
+----------+

计算最佳InnoDB重做日志容量

在高峰流量期间,您可以通过运行以下查询(全部在一行中)来估计重做日志容量大小所需的数量:

经验法则是使重做日志容量足够大,以容纳至少1小时的日志,从而在重做日志的容量太小的情况下,不会迫使InnoDB过于频繁地转储脏页,如果重做日志太大,也不会浪费磁盘和花费太长时间进行恢复。

重做日志使用情况视图

启用适当的InnoDB指标后,还可以查看重做日志的使用情况,并查看我们与软重做日志和硬重做日志逻辑容量的关系:

一天一张图表,医生远离你!

正如我经常说的,对数据库进行趋势分析可以帮助您了解工作负载并防止问题。

我已经用新的MySQL 8.0.30重做日志更新了我的MySQL Shell插件,这些插件为MySQL收集和生成图形。我在前一篇文章中解释了如何使用它。

以下是这些新图表的一些输出:

如果我们查看上图,我们可以看到不同的阈值限制。我们可以看到,我们从来没有触发过什么特别的事情。仅此图表不足以看到我们是否遇到了一些问题。相反,若我们只通过了一条水平线,这将是一个问题。

此图显示了current_lsn和lsn_flushed_to_disk之间的差异。如果差值始终较高,则可能意味着对磁盘的同步操作太慢。

然而,我们可以在图表上看到一些奇怪的东西(用红色箭头表示)。这种差异在很长一段时间内保持不变。这意味着MySQL进程缓冲区中有数据,但无法发送到磁盘上的重做日志文件。下一个图表将为我们提供原因:

我们可以看到,我们两次访问了32个活动的InnoDB重做日志文件。这意味着根本没有备用。这应该是不可能的…除非我们有其他东西也在消耗重做日志。事实上,在另一个会话中,我注册了一个消费者,并没有推进lsn。

我们可以看到,在同一时期,没有新的lsn,也无法写入任何内容。

InnoDB当然无法刷新任何新页面,因为检查点操作(ib_pg_flush_co和ib_ log_checkpt)被阻止,等待重做日志fsync。

在sysbench的输出中,我们可以看到没有进行插入(我使用的是oltp_insert.lua):

qps: 0.00 (r/w/o: 0.00/0.00/0.00)

在MySQL的processlist中,我们可以看到大量的insert查询处于等待处理程序提交状态。

请注意,如果您在该状态下停留600秒,mysqld将故意崩溃!

结论

这种新的InnoDB重做日志架构似乎扩展得非常好,在线动态调整其大小的可能性真的是与众不同!

像往常一样,享受MySQL!

原文标题:Dynamic InnoDB Redo Log
原文作者:LEFRED
原文链接:https://lefred.be/content/dynamic-innodb-redo-log/


免责声明:

1、本站资源由自动抓取工具收集整理于网络。

2、本站不承担由于内容的合法性及真实性所引起的一切争议和法律责任。

3、电子书、小说等仅供网友预览使用,书籍版权归作者或出版社所有。

4、如作者、出版社认为资源涉及侵权,请联系本站,本站将在收到通知书后尽快删除您认为侵权的作品。

5、如果您喜欢本资源,请您支持作者,购买正版内容。

6、资源失效,请下方留言,欢迎分享资源链接

文章评论

0条评论