16.4.1.20 Репликация и MEMORY-таблицы
При остановке и перезапуске сервера-источника репликации его MEMORY-таблицы становятся пустыми. Чтобы воспроизвести этот эффект на репликах, при первом использовании MEMORY-таблицы источником после запуска, он регистрирует событие, уведомляющее реплики о необходимости опустошения таблицы путём записи в бинарный лог оператора DELETE или (с MySQL 5.7.32) оператора TRUNCATE TABLE для этой таблицы. Это генерируемое событие можно идентифицировать по комментарию в бинарном логе, и если на сервере используются GTID, ему присваивается GTID. Оператор всегда записывается в формате оператора, даже если формат протоколирования бинарного лога установлен в ROW, и он записывается даже если режим read_only или super_read_only установлен на сервере. Обратите внимание, что реплика всё ещё содержит устаревшие данные в MEMORY-таблице в период между перезапуском источника и его первым использованием таблицы. Чтобы избежать этого интервала, когда прямой запрос к реплике может вернуть устаревшие данные, вы можете установить системную переменную init_file для указания файла, содержащего операторы, которые заполняют MEMORY-таблицу на источнике при запуске.
При остановке и перезапуске сервера-реплики его MEMORY-таблицы становятся пустыми. Это приводит к тому, что реплика оказывается не синхронизированной с источником и может привести к другим ошибкам или остановке реплики:
Полученные от источника обновления и удаления строк могут завершиться ошибкой
Can't find record in '.memory_table'Операторы, такие как
INSERT INTO ... SELECT FROM, могут вставить другой набор строк на источнике и реплике.memory_table
Реплика также записывает оператор DELETE или (с MySQL 5.7.32) оператор TRUNCATE
TABLE в свой собственный бинарный лог, который передаётся любым последующим репликам, заставляя их опустошать свои MEMORY-таблицы.
Безопасный способ перезапуска реплики, которая дублирует MEMORY-таблицы, заключается в том, чтобы сначала удалить или очистить все строки из MEMORY-таблиц на источнике и подождать, пока эти изменения не будут продублированы на реплике. Затем можно безопасно перезапустить реплику.
В некоторых случаях может применяться альтернативный метод перезапуска. Когда binlog_format=ROW, вы можете предотвратить остановку реплики, если установите slave_exec_mode=IDEMPOTENT перед повторным запуском реплики. Это позволяет реплике продолжить дублирование, но её MEMORY-таблицы всё ещё отличаются от таблиц на источнике. Это приемлемо, если логика приложения такова, что содержимое MEMORY-таблиц может быть безопасно потеряно (например, если MEMORY-таблицы используются для кеширования). slave_exec_mode=IDEMPOTENT применяется глобально ко всем таблицам, поэтому он может скрывать другие ошибки репликации в не-MEMORY-таблицах.
(Описанный метод не применим в NDB Cluster, где slave_exec_mode всегда IDEMPOTENT и не может быть изменён.)
Размер MEMORY-таблиц ограничен значением системной переменной max_heap_table_size, которая не дублируется (см. Раздел 16.4.1.37, «Репликация и переменные»). Изменение max_heap_table_size вступает в силу для MEMORY-таблиц, созданных или обновлённых с помощью ALTER TABLE
... ENGINE = MEMORY или TRUNCATE
TABLE после изменения, или для всех MEMORY-таблиц после перезапуска сервера. Если вы увеличите значение этой переменной на источнике, не сделав этого на реплике, то таблица на источнике может стать больше, чем её аналог на реплике, что приведёт к успешным операциям вставки на источнике и ошибкам «Таблица полна» на реплике. Это известная проблема (Ошибка #48666). В таких случаях необходимо установить глобальное значение max_heap_table_size и на реплике, и на источнике, а затем перезапустить репликацию. Также рекомендуется перезапустить оба сервера MySQL — источник и реплику, чтобы убедиться, что новое значение полностью (глобально) применится на каждом из них.
Дополнительную информацию о MEMORY-таблицах см. в разделе 15.3, «Двигатель хранения MEMORY».
© 2025 Oracle
Licensed under the GPLv2 License.