MySQL 转储和加载 InnoDB 缓冲池(数据预热)

对于性能,拥有一个暖的 InnoDB 缓冲池非常重要。那是什么意思 ?

暖缓冲池意味着生产工作负载所需的最常用的页面(工作集)已经加载到内存中(在缓冲池中)。如果是这样,MySQL 不需要在每次需要最常用的页面时从磁盘读取页面,并在所需数据已经在内存中时加快进程。

当您启动 MySQL 时,默认情况下 InnoDB 缓冲池是冷的,预热过程有时甚至需要几天时间……

因此,您已经可以推断出重新启动 mysqld 是具有冷缓冲池的来源,因为它将开始为空。使用非最佳缓冲池的另一个原因是加载不必要的页面。这可能发生在逻辑转储或加载期间。如果你经常做一个mysqldump例子(不要忘记如果你做逻辑转储,MySQL Shell dump & load 会更好,但也会引入相同的效果)。

但是在 MySQL 中,也有可能处理这样的问题:InnoDB 缓冲池的转储和加载!

有多种方法可以处理 InnoDB 缓冲池转储和加载,让我解释一些场景。

关机时转储,启动时加载

我们必须处理缓冲池的第一个选项是在我们停止 MySQL 时转储其内容。我们并没有真正转储完整的缓冲池,而是转储mysqld正确停止时其中的页面的地址。

事实上,这是现在在 MySQL 中的默认设置,innodb_buffer_pool_dump_at_shutdown是启用的。当然,当 MySQL 启动时,它也会加载innodb_buffer_pool_load_at_startup同样启用的内容。

我们还将在这篇文章的后面看到与此相关的内容……但让我们稍等一下……

按需转储和加载

在 MySQL 中,我们还可以使用innodb_buffer_pool_dump_now. 这将转储磁盘上的当前内容。然后也可以使用innodb_buffer_pool_load_now.

这在 崩溃的情况下也很有用mysqld,因为它不是干净的关闭,缓冲池的内容没有正确转储到磁盘,但将加载手动完成的最新内容。

InnoDB 缓冲池的这种手动转储和加载的主要目的是当会有不同于通常的工作负载时,可以用工作集以外的数据填充缓冲池。例如转储一个完整的大型旧模式。

定期倾倒

可以每隔一段时间转储缓冲池的内容。这在发生崩溃以避免加载旧转储时很有用。

为此,您需要创建一个这样的事件:

CREATE EVENT automatic_buffer_pool_dump
       ON SCHEDULE EVERY 1 HOUR
       DO
          SET global innodb_buffer_pool_dump_now=ON;

让我们来看看如何玩这个以及如何控制它:
测试和示例

我们做的第一件事是控制缓冲池的内容,

mysql> SELECT CONCAT(FORMAT(A.num * 100.0 / B.num,2), '%') BufferPoolFull
       FROM (
         SELECT variable_value num FROM performance_schema.global_status
         WHERE variable_name = 'Innodb_buffer_pool_pages_data') A,
         (SELECT variable_value num FROM performance_schema.global_status
          WHERE variable_name = 'Innodb_buffer_pool_pages_total') B;
 +----------------+
 | BufferPoolFull |
 +----------------+
 | 75.29%         |
 +----------------+
 1 row in set (0.01 sec

我们甚至可以验证缓冲池中加载了哪些模式:

mysql> SELECT object_schema, allocated, data
FROM sys.innodb_buffer_stats_by_schema;
+---------------+-----------+------------+
| object_schema | allocated | data       |
+---------------+-----------+------------+
| sbtest        | 53.22 MiB | 46.97 MiB  |
| mysql         | 5.36 MiB  | 2.72 MiB   |
| query_rewrite | 16.00 KiB |    0 bytes |
+---------------+-----------+------------+

现在我们转储内容:

mysql> SET global innodb_buffer_pool_dump_now=ON;
Query OK, 0 rows affected (0.00 sec)

在错误日志中,我们可以看到以下消息:

mysql> select LOGGEND, DATA from performance_schema.error_log order by 1 desc limit 2;
+-------------+---------------------------------------------------------+
| LOGGED      | DATA                                                    |
+-------------+---------------------------------------------------------+
| 2021-06-16. | Buffer pool(s) dump completed at 210616 14:25:39        |
| 2021-06-16. | Dumping buffer pool(s) to /var/lib/mysql/ib_buffer_pool |
+-------------+---------------------------------------------------------+

在文件系统上:

[root@imac mysql]# ls -lh ib_buffer_pool
 -rw-r----- 1 mysql mysql 20K Jun 16 14:25 ib_buffer_pool

我们重新启动 MySQL 并再次检查:

+----------------+
| BufferPoolFull |
+----------------+
| 26.12%         |
+----------------+


嗯……发生了什么事?这不是我所期望的……

事实上,这是我的错,我没有仔细阅读文档,我的同事 Marcin Babij 向我指出了原因:innodb_buffer_pool_dump_pct.

默认情况下的值innodb_buffer_pool_dump_pct是25!

为了让它按预期工作,如果你想完全转储和加载它,你需要将它设置为100。

+----------------+
| BufferPoolFull |
+----------------+
| 99.10%         |
+----------------+
1 row in set (0.00 sec)

mysql> SET GLOBAL innodb_buffer_pool_dump_pct = 100;

然后我重新启动 MySQL(我在启动时禁用了缓冲池的负载):

+----------------+
| BufferPoolFull |
+----------------+
| 18.70%         |
+----------------+
 1 row in set (0.00 sec)

mysql> SET global innodb_buffer_pool_load_now=ON;
Query OK, 0 rows affected (0.00 sec)

+----------------+
| BufferPoolFull |
+----------------+
| 99.94%         |
+----------------+
1 row in set (0.01 sec)

因此,现在您知道如何处理 MySQL InnoDB 缓冲池预热以及如何进行是否计划执行可能严重影响内存中工作集的异常查询。

原文链接:https://lefred.be/content/mysql-dump-load-innodb-buffer-pool/

posted @ 2021-08-06 12:14  VicLW  阅读(678)  评论(0编辑  收藏  举报