Назад | Перейти на главную страницу

Журнал отмены MySQL 8 не усекается после чрезмерного роста

Видимо я начал SELECT запрос 20 дней назад, который так и не был завершен. Он продолжал работать, даже несмотря на то, что клиент отключился, и работал так долго, что один из журналов отмены увеличился до 230 ГБ. (Рассматриваемая база данных составляет 320 ГБ данных). Я принудительно прервал запрос, но журнал отмены просто не уменьшился до нормального размера, в результате чего диск был заполнен.

Для записи это размеры на диске:

root@the-db:/var/lib/mysql# du -h undo_00* erik_*
11G undo_001
244G    undo_002
1.5G    erik_temporary_undo_004.ibu
22G erik_undo_003.ibu

Интересно, что все журналы отмены довольно большие?

Я попытался разобраться в документации, но не могу заставить ее работать: https://dev.mysql.com/doc/refman/8.0/en/innodb-undo-tablespaces.html

Версия работает:

root@the-db:/var/lib/mysql# mysql --version
mysql  Ver 8.0.18 for Linux on x86_64 (MySQL Community Server - GPL)

Автоматическое усечение

Если я правильно понимаю, чтобы поток очистки обрезал журнал отмены автоматически, необходимо выполнение трех условий:

Шаг 1. Журнал отмены должен быть больше, чем @@innodb_max_undo_log_size, который:

mysql> SELECT @@innodb_max_undo_log_size;
+----------------------------+
| @@innodb_max_undo_log_size |
+----------------------------+
|                 1073741824 |
+----------------------------+

Шаг 2. @@innodb_undo_log_truncate должно быть ON

mysql> select @@innodb_undo_log_truncate;
+----------------------------+
| @@innodb_undo_log_truncate |
+----------------------------+
|                          1 |
+----------------------------+

Шаг 3. Всего должно быть 2 активных журнала отмены. Automated truncation of undo tablespaces requires a minimum of two active undo tablespaces (не уверен, что это означает 2 активных перед один выводится из вращения для усечения).

mysql> SELECT NAME, SPACE_TYPE, STATE FROM INFORMATION_SCHEMA.INNODB_TABLESPACES WHERE SPACE_TYPE = 'Undo' ORDER BY NAME;
+-------------------------+------------+----------+
| NAME                    | SPACE_TYPE | STATE    |
+-------------------------+------------+----------+
| erik_temporary_undo_003 | Undo       | active   |
| erik_temporary_undo_004 | Undo       | active   |
| innodb_undo_001         | Undo       | active   |
| innodb_undo_002         | Undo       | inactive |
+-------------------------+------------+----------+

Согласно вышесказанному, у нас есть 3 активных и 4 полных журнала отмены.

Однако вроде ничего не происходит.

Усечение вручную

Также существует ручной процесс усечения журнала, который имеет другой набор предварительных требований.

Шаги 1 и 2 одинаковы для автоматического усечения.

Шаг 3 отличается тем, что Manual truncation of undo tablespaces requires a minimum of three active undo tablespaces (все еще не уверен, означает ли это, что 3 активны, прежде чем один будет выведен из вращения). Чтобы обойти мою неуверенность, я создал 2 дополнительных табличных пространства отмены.

CREATE UNDO TABLESPACE erik_temporary_undo_003 ADD DATAFILE 'erik_undo_003.ibu';
CREATE UNDO TABLESPACE erik_temporary_undo_004 ADD DATAFILE 'erik_temporary_undo_004.ibu';

Шаг 4 - деактивировать табличное пространство, требующее усечения:

ALTER UNDO TABLESPACE innodb_undo_002 SET INACTIVE;

Если я правильно понимаю, это вызовет усечение, и после его завершения STATUS будет empty. Опять же, вот текущий статус:

mysql> SELECT NAME, SPACE_TYPE, STATE FROM INFORMATION_SCHEMA.INNODB_TABLESPACES WHERE SPACE_TYPE = 'Undo' ORDER BY NAME;
+-------------------------+------------+----------+
| NAME                    | SPACE_TYPE | STATE    |
+-------------------------+------------+----------+
| erik_temporary_undo_003 | Undo       | active   |
| erik_temporary_undo_004 | Undo       | active   |
| innodb_undo_001         | Undo       | active   |
| innodb_undo_002         | Undo       | inactive |
+-------------------------+------------+----------+

Он был отключен около 3 дней назад и с тех пор не менялся.

Одна странность заключается в том, что, согласно следующему запросу, существует только 2 активных журнала отмены, тогда как предыдущий запрос показывает 3. Я что-то упускаю?

mysql> SHOW STATUS LIKE 'Innodb_undo_tablespaces%';
+----------------------------------+-------+
| Variable_name                    | Value |
+----------------------------------+-------+
| Innodb_undo_tablespaces_total    | 4     |
| Innodb_undo_tablespaces_implicit | 2     |
| Innodb_undo_tablespaces_explicit | 2     |
| Innodb_undo_tablespaces_active   | 2     |
+----------------------------------+-------+

Не должен Innodb_undo_tablespaces_active быть как минимум 3?

Частота

В документации упоминается innodb_purge_rseg_truncate_frequency как способ заставить поток очистки запускаться чаще. По умолчанию 128 и в примере показано, как установить его на 32. Что это на самом деле означает с точки зрения времени, очень неясно. Здесь просто упоминается «каждые 32 забега».

To increase that frequency, decrease the innodb_purge_rseg_truncate_frequency setting. For example, to have the purge thread look for undo tabespaces once every 32 timees[sic] that purge is invoked, set innodb_purge_rseg_truncate_frequency to 32.

Для удобства я установил его на 1.

mysql> show variables like "%truncate%";
+--------------------------------------+-------+
| Variable_name                        | Value |
+--------------------------------------+-------+
| innodb_purge_rseg_truncate_frequency | 1     |
| innodb_undo_log_truncate             | ON    |
+--------------------------------------+-------+

Метрики

Я совсем недавно понял, как получить метрики InnoDB:

mysql> set global innodb_monitor_enable = all;

И будет обновлять метрики, когда они станут доступны.

Соответствующие конфиги

mysql> show variables like "%undo%";
+--------------------------+------------+
| Variable_name            | Value      |
+--------------------------+------------+
| innodb_max_undo_log_size | 1073741824 |
| innodb_undo_directory    | ./         |
| innodb_undo_log_encrypt  | OFF        |
| innodb_undo_log_truncate | ON         |
| innodb_undo_tablespaces  | 2          |
+--------------------------+------------+

mysql> show variables like "%truncate%";
+--------------------------------------+-------+
| Variable_name                        | Value |
+--------------------------------------+-------+
| innodb_purge_rseg_truncate_frequency | 1     |
| innodb_undo_log_truncate             | ON    |
+--------------------------------------+-------+

Что мне не хватает, чтобы MySQL сократил размер журнала отмены?

Я просто предполагаю, что усечение означает, что фактический файл на диске сжимается. Может это что-то значит?