Перейти к содержанию

Улучшения бинарного журнала и репликации

Благодаря постоянному развитию в MyDB Сервер для MySQL вошли ряд улучшений, связанные с репликацией и обработкой бинарных журналов. Это привело к особенностям репликации, отличающим ее от MySQL.

Безопасность операторов с указанием LIMIT

Краткое описание исправления

MySQL рассматривает все команды UPDATE/DELETE/INSERT ... SELECT с указанием LIMIT как небезопасные, независимо от того, действительно ли они производят недетерминированный результат, и переключает режим бинарного журнала с режима statement-based на row-based. MyDB Сервер для MySQL более точен, он рассматривает такие команды как безопасные, если они содержат ORDER BY PK или условие WHERE. Это исправление было перенесено из отчета об ошибке MySQL #42415 (#44).

Улучшение производительности при обновлении положения журнала ретрансляции

Исправление положения журнала ретрансляции

MySQL всегда обновляет позицию журнала ретрансляции в настройках репликации с несколькими источниками независимо от того, была ли уже выполнены зафиксированная транзакция или нет. MyDB Сервер пропускает обновления положения журнала ретрансляции для уже зарегистрированных GTID.

Детали положения журнала ретрансляции

В частности, такие безусловные обновления положения журнала ретрансляции вызывали дополнительные операции fsync в случае relay-log-info-repository=TABLE и с большим количеством каналов, передающих такие дублирующие (уже выполненные) транзакции, ситуация становилась хуже пропорционально. Исправлена ошибка #1786 (MySQL #85141).

Улучшение производительности при обновлении источника и статуса соединения

Исправление обновления источника и статуса соединения.

Реплики, настроенные для обновления состояния источника и информации о соединении только при ротации файла журнала, не наблюдали ожидаемого снижения нагрузки. MySQL дополнительно обновлял эту информацию в случае наличия нескольких источников репликация, когда реплике приходилось пропустить уже выполненное событие GTID.

Подробности об источнике и состоянии соединения

Конфигурация с master_info_repository=TABLE и sync_master_info=0 заставляет реплику обновлять информацию о состоянии источника и соединения в специальной таблице только при ротации файлов журнала, а не после каждых sync_master_info событий. Но эта функциональность не работала в конфигурациях репликации с несколькими источниками. Сигналы Heartbeat, отправляемые на реплику, чтобы пропустить события GTID, которые она уже выполнила, ранее оценивались как события ротации журнала ретрансляции и приводили к синхронизации таблицы mysql.slave_master_info. Эта неточность могла привести к огромному (вплоть до 5 раз при некоторых настройках) увеличению нагрузки на запись на реплике до того, как проблема была исправлена в Percona Server for MySQL. Исправлена ошибка #1812 (MySQL #85158).

Запись команд FLUSH в бинарный журнал

Команды FLUSH, такие как FLUSH SLOW LOGS, не записываются в бинарный журнал, если системная переменная binlog_skip_flush_commands установлена в ON.

Кроме того, были реализованы следующие изменения в поведении режимов read_only и super_read_only:

  • Когда для read_only установлено значение ON, любая команда FLUSH ..., выполняемая обычным пользователем (без привилегии SUPER), не записывается в бинарный журнал независимо от значения переменной binlog_skip_flush_commands.

  • Когда для параметра super_read_only установлено значение ON, любая команда FLUSH ..., выполняемая любым пользователем (даже обладающим привилегией SUPER), не записывается в бинарный журнал независимо от значения переменной binlog_skip_flush_commands.

Попытка запустить команду FLUSH без привилегий SUPER или RELOAD приводит к ошибке ER_SPECIFIC_ACCESS_DENIED_ERROR независимо от значения переменной binlog_skip_flush_commands.

binlog_skip_flush_commands

Свойство Значение
Командная строка Да
Конфигурационный файл Да
Область видимости Глобальная
Динамическая Да
По умолчанию OFF

Когда для binlog_skip_flush_commands установлено значение ON, команды FLUSH ... не записываются в бинарный журнал. Дополнительную информацию о том, что ещё влияет на запись команд FLUSH в бинарный журнал, см. в разделе «Запись команд FLUSH в бинарный журнал».

Примечание

FLUSH LOGS, FLUSH BINARY LOGS, FLUSH TABLES WITH READ LOCK и FLUSH TABLES ... FOR EXPORT не записываются в бинарный журнал независимо от того, какое значение содержит переменная binlog_skip_flush_commands. Команда FLUSH не записывается в бинарный журнал, а значение binlog_skip_flush_commands игнорируется, если команда FLUSH запускается с ключевым словом NO_WRITE_TO_BINLOG (или его псевдонимом LOCAL).

Сохранение комментариев в DROP TABLE

Когда вы выполняете команду DROP TABLE, бинарный журнал сохраняет команду, но удаляет комментарии и заключает имя таблицы в кавычки. Если вам требуется, чтобы бинарный журнал сохранял комментарии и не добавлял кавычки, включите опцию binlog_ddl_skip_rewrite.

binlog_ddl_skip_rewrite

Свойство Значение
Командная строка Да
Конфигурационный файл Да
Область видимости Глобальная
Динамическая Да
По умолчанию OFF

Если переменная включена, DDL-команды DROP TABLE для одной таблицы регистрируются в бинарном журнале с комментариями. DDL-команды DROP TABLE для нескольких таблиц не поддерживаются и возвращают ошибку.

SET binlog_ddl_skip_rewrite = ON;
/*comment at start*/DROP TABLE t /*comment at end*/;

Пользовательские функции бинарного журнала

Чтобы реализовать восстановление на определенный момент времени (point in time recovery), мы добавили binlog_utils_udf. Включены следующие определяемые пользователем функции:

Имя Возвращает Описание
get_binlog_by_gtid() Имя файла бинлога в виде строки Возвращает имя файла бинлога, содержащего указанный GTID
get_last_gtid_from_binlog() GTID в виде строки Возвращает последний GTID в указанном бинлоге
get_gtid_set_by_binlog() Набор GTID в виде строки Возвращает все GTID в указанном бинлоге
get_binlog_by_gtid_set() Имя файла бинлога в виде строки Возвращает имя файла бинлога, который содержит хотя бы один GTID из указанного набора
get_first_record_timestamp_by_binlog() Временную метку в виде целого числа Возвращает временную метку первого события в указанном бинлоге
get_last_record_timestamp_by_binlog() Временную метку в виде целого числа Возвращает временную метку последнего события в указанном бинлоге

Примечание

Все функции, возвращающие временные метки, возвращают свои значения в формате UNIX-времени с точностью до микросекунды. Другими словами, они представляют собой количество микросекунд, прошедших с 1 января 1970 года.

Все функции, принимающие имя бинарного журнала в качестве параметра, принимают только короткие имена без компонента пути. Если во входных данных обнаружен разделитель пути (/), возвращается ошибка. Это требуется для ограничения путей, из которых можно читать бинарные журналы. Они всегда считываются из текущего каталога для бинарных журналов (системная переменная @@log_bin_basename).

Все функции, возвращающие имена файлов бинарного журнала, возвращают имя в краткой форме, без компонента пути.

Основной синтаксис get_binlog_by_gtid() следующий:

* get_binlog_by_gtid(string) [AS] alias

Использование: SELECT get_binlog_by_gtid(string) [AS] alias

Пример:

CREATE FUNCTION get_binlog_by_gtid RETURNS STRING SONAME 'binlog_utils_udf.so';
SELECT get_binlog_by_gtid("F6F54186-8495-47B3-8D9F-011DDB1B65B3:1") AS result;
Ожидаемый результат
+--------------+
| result       |
+==============+
| binlog.00001 |
+--------------+
DROP FUNCTION get_binlog_by_gtid;

Основной синтаксис get_last_gtid_from_binlog() следующий:

* get_last_gtid_from_binlog(string) [AS] alias

Использование: SELECT get_last_gtid_from_binlog(string) [AS] alias

Например:

CREATE FUNCTION get_last_gtid_from_binlog RETURNS STRING SONAME 'binlog_utils_udf.so';
SELECT get_last_gtid_from_binlog("binlog.00001") AS result;
Ожидаемый результат
+-----------------------------------------+
| result                                  |
+=========================================+
| F6F54186-8495-47B3-8D9F-011DDB1B65B3:10 |
+-----------------------------------------+
DROP FUNCTION get_last_gtid_from_binlog;

Основной синтаксис get_gtid_set_by_binlog() следующий:

* get_gtid_set_by_binlog(string) [AS] alias

Использование: SELECT get_gtid_set_by_binlog(string) [AS] alias

Например:

CREATE FUNCTION get_gtid_set_by_binlog RETURNS STRING SONAME 'binlog_utils_udf.so';
SELECT get_gtid_set_by_binlog("binlog.00001") AS result;
Ожидаемый результат
+-------------------------+
| result                  |
+=========================+
| 11ea-b9a7:7,11ea-b9a7:8 |
+-------------------------+
DROP FUNCTION get_gtid_set_by_binlog;

Основной синтаксис get_binlog_by_gtid_set() следующий:

* get_binlog_by_gtid_set(string) [AS] alias

Использование: SELECT get_binlog_by_gtid_set(string) [AS] alias

Пример:

CREATE FUNCTION get_binlog_by_gtid_set RETURNS STRING SONAME 'binlog_utils_udf.so';
SELECT get_binlog_by_gtid_set("11ea-b9a7:7,11ea-b9a7:8") AS result;
Ожидаемый результат
+---------------------------------------------------------------+
| result                                                        |
+===============================================================+
| bin.000003                                                    |
+---------------------------------------------------------------+
DROP FUNCTION get_binlog_by_gtid_set;

Основной синтаксис get_first_record_timestamp_by_binlog() следующий:

* get_first_record_timestamp_by_binlog(TIMESTAMP) [AS] alias

Использование: SELECT get_first_record_timestamp_by_binlog(TIMESTAMP) [AS] alias

Например:

CREATE FUNCTION get_first_record_timestamp_by_binlog RETURNS INTEGER SONAME 'binlog_utils_udf.so';
SELECT FROM_UNIXTIME(get_first_record_timestamp_by_binlog("bin.00003") DIV 1000000) AS result;
Ожидаемый результат
+---------------------+
| result              |
+=====================+
| 2020-12-03 09:10:40 |
+---------------------+
DROP FUNCTION get_first_record_timestamp_by_binlog;

Основной синтаксис get_last_record_timestamp_by_binlog() следующий:

* get_last_record_timestamp_by_binlog(TIMESTAMP) [AS] alias

Использование: SELECT get_last_record_timestamp_by_binlog(TIMESTAMP) [AS] alias

Например:

CREATE FUNCTION get_last_record_timestamp_by_binlog RETURNS INTEGER SONAME 'binlog_utils_udf.so';
SELECT FROM_UNIXTIME(get_last_record_timestamp_by_binlog("bin.00003") DIV 1000000) AS result;
Ожидаемый результат
+---------------------+
| result              |
+=====================+
| 2020-12-04 04:18:56 |
+---------------------+
DROP FUNCTION get_last_record_timestamp_by_binlog;

Ограничения

Для следующих переменных не присваивайте значения с одним или несколькими символами точки (.):

Значение, определенное с помощью этих символов, обрабатывается по-разному в MySQL и Percona XtraBackup и может привести к непредсказуемому поведению.


Последнее обновление: 2024-04-30