25.7.11 Репликация NDB Cluster с использованием многопоточного приложения
Репликация NDB в NDB 8.4 поддерживает использование механизма многопоточного приложения MySQL Server (MTA), который позволяет независимым бинарным логам транзакций применяться параллельно на реплике, увеличивая пиковую пропускную способность репликации.
Требования
Реализация MTA MySQL Server делегирует обработку отдельных бинарных транзакций журнала пулу потоков-работников (размер которого настраивается) и координирует потоки-работников, чтобы гарантировать соблюдение зависимостей транзакций, закодированных в бинарном журнале, и поддержание порядка подтверждения при необходимости (см. Раздел 19.2.3, «Потоки репликации»). Для использования этой функциональности с NDB Cluster необходимо, чтобы реплика была настроена на использование нескольких потоков-работников. Для этого установите replica_parallel_workers для управления количеством потоков-работников на реплике. Значение по умолчанию равно 4.
Настройка MTA: Источник
Если установлено на источнике mysqld, replica_parallel_type должно быть LOGICAL_CLOCK (значение по умолчанию).
NDB не поддерживает replica_parallel_type=DATABASE.
Кроме того, рекомендуется установить объем памяти, используемой для отслеживания наборов записей бинарных транзакций журнала на источнике (binlog_transaction_dependency_history_size) до , где E *
PE — средний размер эпохи (как количество операций в эпоху), а P — максимальная ожидаемая параллельность. Дополнительную информацию см. в разделе Использование памяти для отслеживания набора записей.
Настройка MTA: Реплика
Настройка реплики mysqld для MTA требует, чтобы replica_parallel_workers было больше 1. Рекомендуемое начальное значение при первом включении MTA — 4, что является значением по умолчанию.
Кроме того, replica_preserve_commit_order должно быть ON. Это также значение по умолчанию.
Зависимость транзакций и обработка набора записей
Зависимости транзакций обнаруживаются с помощью анализа набора записей каждой транзакции, то есть набора строк (таблица, значения ключей), записанных транзакцией. Если две транзакции изменяют одну и ту же строку, они считаются зависимыми и должны применяться в порядке (то есть последовательно) для предотвращения тупиков или неправильных результатов. Если в таблице есть вторичные уникальные ключи, эти значения также добавляются в набор записей транзакции для обнаружения случаев, когда существуют зависимости транзакций, подразумеваемые разными транзакциями, влияющими на одно и то же значение уникального ключа, и поэтому требующие упорядочения. Если зависимости не могут быть эффективно определены, mysqld переходит к рассмотрению транзакций как зависимых по соображениям безопасности.
Зависимости транзакций кодируются в бинарном журнале источником mysqld. Зависимости закодированы в событии ANONYMOUS_GTID с использованием схемы «Логические часы». (См. Раздел 19.1.4.1, «Понятия репликации».)
Реализация набора записей, используемая MySQL (и NDB Cluster), использует основанное на хэшировании обнаружение конфликтов на основе соответствия 64-битным хэшам строк соответствующих значений таблиц и индексов. Это надежно обнаруживает, когда одно и то же значение ключа встречается дважды, но также может давать ложные срабатывания, если различные значения таблиц и индексов хешируются до одного и того же 64-битного значения; это может привести к искусственным зависимостям, которые могут снизить доступную параллельность.
Зависимости транзакций принуждаются любым из следующих способов:
Операции DDL
Вращение бинарного журнала или столкновение с границами файлов бинарного журнала
Ограничения размера истории набора записей
-
Записи, которые ссылаются на родительские внешние ключи в целевой таблице
Более конкретно, транзакции, которые выполняют вставки, обновления и удаления по родительским таблицам внешних ключей, сериализуются относительно всех предыдущих и последующих транзакций, а не только тех транзакций, которые влияют на таблицы, участвующие в отношении ограничений. И наоборот, транзакции, выполняющие вставки, обновления и удаления по дочерним таблицам внешних ключей (ссылающимся), не сериализуются особенно по отношению друг к другу.
Реализация MTA MySQL пытается применить независимые бинарные транзакции журнала параллельно. NDB записывает все изменения, происходящие во всех пользовательских транзакциях, подтверждаемых в эпоху (TimeBetweenEpochs, по умолчанию 100 миллисекунд), в одной бинарной транзакции журнала, называемой эпохальной транзакцией. Таким образом, для того чтобы две последовательные эпохальные транзакции были независимыми и могли применяться параллельно, необходимо, чтобы ни одна строка не изменялась в обеих эпохах. Если любая строка изменена в обеих эпохах, то они зависимы и применяются последовательно, что может ограничить доступную параллельность.
Эпохальные транзакции считаются независимыми на основе набора строк, измененных на кластере-источнике в эпоху, но не включая сгенерированные mysql.ndb_apply_status WRITE_ROW события, которые передают метаданные эпохи. Это предотвращает каждую эпохальную транзакцию от тривиальной зависимости от предыдущей эпохи, но требует, чтобы журнал binlog применялся на реплике с сохранением порядка подтверждения. Это также подразумевает, что бинарный журнал NDB с зависимостями набора записей не подходит для использования базой данных-репликой, использующей другой движок хранилища MySQL.
Возможно или желательно изменить поведение транзакций приложения, чтобы избежать повторяющихся изменений одних и тех же строк в отдельных транзакциях в течение короткого промежутка времени, чтобы увеличить доступную параллельность применения.
Использование памяти для отслеживания набора записей
Объем памяти, используемой для отслеживания наборов записей бинарных транзакций журнала, может быть установлен с помощью системной переменной сервера binlog_transaction_dependency_history_size, которая по умолчанию равна 25000 хэшам строк.
Если средняя транзакция бинарного журнала изменяет N строк, то для того, чтобы иметь возможность идентифицировать независимые (параллелизуемые) транзакции до уровня параллельности P, нам нужно, чтобы binlog_transaction_dependency_history_size было как минимум . (Максимальное значение — 1000000.)N *
P
Конечный размер истории приводит к конечному максимальному длине зависимости, которая может быть надежно определена, что дает конечную параллельность, которая может быть выражена. Любая строка, не найденная в истории, может зависеть от последней транзакции, удаленной из истории.
История набора записей не действует как скользящее окно последних N транзакций; вместо этого это конечный буфер, который разрешается полностью заполниться, а затем его содержимое полностью удаляется, когда он становится полным. Это означает, что размер истории следует за пилообразным шаблоном со временем, и, следовательно, максимальная определяемая длина зависимости также следует за пилообразным шаблоном со временем, так что независимые транзакции все еще могут быть помечены как зависимые, если буфер истории набора записей был сброшен между их обработкой.
В этой схеме каждая транзакция в файле бинарного журнала аннотируется sequence_number (1, 2, 3, ...), а также номером последовательности последней бинарной транзакции журнала, на которой она зависит, которую мы называем last_committed.
В рамках данного файла бинарного журнала первая транзакция имеет sequence_number 1 и last_committed 0.
Если бинарная транзакция журнала зависит от своего непосредственного предшественника, ее применение сериализовано. Если зависимость от более ранней транзакции, то возможно применение транзакции параллельно с предыдущими независимыми транзакциями.
Содержимое событий ANONYMOUS_GTID, включая sequence_number и last_committed (и, следовательно, зависимости транзакций), можно увидеть с помощью mysqlbinlog.
События ANONYMOUS_GTID, генерируемые на источнике, обрабатываются отдельно от сжатой транзакционной полезной нагрузки с объёмными событиями BEGIN, TABLE_MAP*, WRITE_ROW*, UPDATE_ROW*, DELETE_ROW* и COMMIT, что позволяет определить зависимости до разархивирования. Это означает, что поток координатора реплики может делегировать разархивирование полезной нагрузки транзакции потоку-рабочему, обеспечивая автоматическое параллельное разархивирование независимых транзакций на реплике.
Известные ограничения
Вторичные уникальные столбцы. Таблицы со вторичными уникальными столбцами (то есть уникальными ключами, отличными от первичного ключа) отправляют все столбцы на источник, чтобы можно было обнаружить конфликты, связанные с уникальными ключами.
В случае, когда текущий режим двоичного протоколирования не включает все столбцы, а только изменённые столбцы (--ndb-log-updated-only=OFF, --ndb-log-update-minimal=ON, --ndb-log-update-as-write=OFF), это может увеличить объём данных, отправляемых от узлов данных к узлам SQL.
Влияние зависит как от скорости изменения (обновления или удаления) строк в таких таблицах, так и от объёма данных в столбцах, которые фактически не изменяются.
Репликация NDB в InnoDB. Модуль отслеживания зависимостей транзакций NDB двоичного журнализатора намеренно игнорирует межтранзакционные зависимости, созданные событиями метаданных mysql.ndb_apply_status, которые обрабатываются отдельно в рамках завершения транзакции эпохи на прикладном уровне репликации. Для репликации в InnoDB специальной обработки нет; это может привести к снижению производительности или другим проблемам при использовании многопоточного приложения InnoDB для обработки двоичного журнала NDB MTA.
© 2025 Oracle
Licensed under the GPLv2 License.