Spec-Zone .ru
спецификации, руководства, описания, API

17.6.11. MySQL Cluster Replication Conflict Resolution

При использовании установки репликации, включающей многократные ведущие устройства (включая круговую репликацию), возможно, что различные ведущие устройства могут попытаться обновить ту же самую строку на ведомом устройстве с различными данными. Разрешение конфликтов в MySQL Cluster Replication обеспечивает средство разрешения таких конфликтов, разрешая определяемый пользователем столбец разрешения использоваться, чтобы определить, должно ли обновление о данном ведущем устройстве быть применено на ведомое устройство.

Некоторые типы разрешения конфликтов, поддерживаемого MySQL Cluster (NDB$OLD(), NDB$MAX(), NDB$MAX_DELETE_WIN()) реализуйте этот определяемый пользователем столбец как столбец "метки времени" (хотя его тип не может быть TIMESTAMP, как объяснено позже в этом разделе). Эти типы разрешения конфликтов всегда применяются основание строки строкой, а не транзакционное основание. Основанные на эпохе функции разрешения конфликтов NDB$EPOCH() и NDB$EPOCH_TRANS() сравните порядок, в который эпохи тиражируются (и таким образом эти функции являются транзакционными). Различные методы могут использоваться, чтобы сравнить значения столбцов разрешения на ведомом устройстве, когда конфликты происходят, как объяснено позже в этом разделе; используемый метод может быть установлен на основе на таблицу.

Следует также иметь в виду, что это - обязанность приложения гарантировать, что столбец разрешения правильно заполняется с соответствующими значениями, так, чтобы функция разрешения могла сделать соответствующий выбор, определяя, применить ли обновление.

Требования. Приготовления к разрешению конфликтов должны быть сделаны и на ведущем устройстве и на ведомом устройстве. Эти задачи описываются в следующем списке:

При использовании функций NDB$OLD(), NDB$MAX(), и NDB$MAX_DELETE_WIN() для основанного на метке времени разрешения конфликтов мы часто обращаемся к столбцу, используемому для того, чтобы определить обновления как столбец "метки времени". Однако, тип данных этого столбца никогда не TIMESTAMP; вместо этого, его тип данных должен быть INT (INTEGER) или BIGINT. Столбец "метки времени" должен также быть UNSIGNED и NOT NULL.

NDB$EPOCH() и NDB$EPOCH_TRANS() функции, обсужденные позже в этом разделе, работают, сравнивая относительный порядок эпох репликации, примененных на основной и вторичный MySQL Cluster, и не используют метки времени.

Основное управление столбцом. Мы можем видеть операции обновления с точки зрения "прежде" и "после" изображений — то есть, состояния таблицы прежде и после того, как обновление применяется. Обычно, обновляя таблицу с первичным ключом, "прежде, чем" изображение не очень интересно; однако, когда мы должны определить на основе на обновление, использовать ли обновленные значения на ведомом устройстве репликации, мы должны удостовериться, что оба изображения пишутся двоичному журналу ведущего устройства. Это делается с --ndb-log-update-as-write опция для mysqld, как описано позже в этом разделе.

Важный

Делается ли журналирование полных строк или обновленных столбцов только, решается, когда сервер MySQL запускается, и не может быть изменен онлайн; следует или перезапустить mysqld, или запустить новый mysqld экземпляр с различных опций журналирования.

Журналирование Всех или Частичных Строк (--ndb-log-updated-only Опция)

Формат командной строки --ndb-log-updated-only
Формат файла опции ndb_log_updated_only
Системное Имя переменной ndb_log_updated_only
Переменный Контекст Глобальная переменная
Динамическая Переменная Да
Разрешенные Значения
Ввести boolean
Значение по умолчанию ON

В целях разрешения конфликтов есть два основных метода журналирования строк, как определено установкой --ndb-log-updated-only опция для mysqld:

Это обычно достаточно — и более эффективно — зарегистрировать обновленные столбцы только; однако, если Вы должны зарегистрировать все строки, можно сделать так, устанавливая --ndb-log-updated-only к 0 или OFF.

--ndb-log-update-as-write Опция: Регистрация Измененных Данных как Обновления

Формат командной строки --ndb-log-update-as-write
Формат файла опции ndb-log-update-as-write
Системное Имя переменной ndb_log_update_as_write
Переменный Контекст Глобальная переменная
Динамическая Переменная Да
Разрешенные Значения
Ввести boolean
Значение по умолчанию ON

Установка Сервера MySQL --ndb-log-update-as-write опция определяет, выполняется ли журналирование с или без "перед" изображением. Поскольку разрешение конфликтов делается в обработчике обновления Сервера MySQL, необходимо управлять входом в систему ведущего устройства, так, что обновляет, обновления и не записи; то есть, так, что обновляет, обрабатываются как изменения в существующих строках, а не записи новых строк (даже при том, что они заменяют существующие строки). Эта опция включается по умолчанию; другими словами обновления обрабатываются как записи. (Таким образом, обновления по умолчанию пишутся как write_row события в двоичном журнале, а не как update_row события.), Чтобы выключить опцию, запустите основной mysqld с --ndb-log-update-as-write=0 или --ndb-log-update-as-write=OFF.

Управление разрешением конфликтов. Разрешение конфликтов обычно включается на сервере, где конфликты могут произойти. Как журналирование выбора метода, это включается записями в mysql.ndb_replication таблица.

ndb_replication системная таблица. Чтобы включить разрешению конфликтов, необходимо создать ndb_replication таблица в mysql системная база данных на ведущем устройстве, ведомом устройстве, или и, в зависимости от типа разрешения конфликтов и, в зависимости от метода, который будет использоваться. Эта таблица используется, чтобы управлять функциями журналирования и разрешения конфликтов на основе на таблицу, и ссорится на таблицу, включенную в репликацию. ndb_replication создается и заполняется управляющей информацией на сервере, где конфликт должен быть разрешен. В простой основной ведомой установке, где данные могут также быть изменены локально на ведомом устройстве, это обычно будет ведомым устройством. В более сложной основной основной схеме репликации (с 2 путями) это обычно будет всеми включенными ведущими устройствами. Каждая строка в mysql.ndb_replication соответствует таблице, тиражируемой, и определяет, как зарегистрировать и разрешить конфликты (то есть, который функция разрешения конфликтов, если таковые вообще имеются, чтобы использовать) для той таблицы. Определение mysql.ndb_replication таблицу показывают здесь:

CREATE TABLE mysql.ndb_replication  (    db VARBINARY(63),    table_name VARBINARY(63),    server_id INT UNSIGNED,    binlog_type INT UNSIGNED,    conflict_fn VARBINARY(128),    PRIMARY KEY USING HASH (db, table_name, server_id))   ENGINE=NDBPARTITION BY KEY(db,table_name);

Столбцы в этой таблице описываются в следующих немногих абзацах.

db. Имя базы данных, содержащей таблицу, которая будет тиражирована.

table_name. Имя таблицы, которая будет тиражирована.

server_id. Уникальный ID сервера экземпляра MySQL (узел SQL), где таблица находится.

binlog_type. Тип двоичного журналирования, которое будет использоваться. Это определяется как показано в следующей таблице:

Значение Внутреннее Значение Описание
0 NBT_DEFAULT Используйте значение по умолчанию сервера
1 NBT_NO_LOGGING Не регистрируйте эту таблицу в двоичном журнале
2 NBT_UPDATED_ONLY Только обновленные атрибуты регистрируются
3 NBT_FULL Зарегистрируйте всю строку, даже если не обновленный (поведение значения по умолчанию сервера MySQL)
4 NBT_USE_UPDATE (Для того, чтобы генерировать NBT_UPDATED_ONLY_USE_UPDATE и NBT_FULL_USE_UPDATE значения только — не предназначенный для отдельного использования)
5 [Не используемый] ---
6 NBT_UPDATED_ONLY_USE_UPDATE (равный NBT_UPDATED_ONLY | NBT_USE_UPDATE) Используйте обновленные атрибуты, даже если значения неизменны
7 NBT_FULL_USE_UPDATE (равный NBT_FULL |NBT_USE_UPDATE) Используйте всю строку, даже если значения неизменны

conflict_fn. Функция разрешения конфликтов, которая будет применена. Эта функция должна быть определена как один из показанных в следующем списке:

Эти функции описываются в следующих немногих абзацах.

NDB$OLD(column_name). Если значение column_name то же самое и на ведущем устройстве и на ведомом устройстве, тогда обновление применяется; иначе, обновление не применяется на ведомое устройство, и исключение пишется журналу. Это иллюстрируется следующим псевдокодом:

if (master_old_column_value == slave_current_column_value)  apply_update();else  log_exception();

Эта функция может использоваться для "того же самого разрешения конфликтов" побед значения. Этот тип разрешения конфликтов гарантирует, что обновления не применяются на ведомое устройство от неправильного ведущего устройства.

Важный

Значение столбца от ведущего устройства "перед" изображением используется этой функцией.

NDB$MAX(column_name). Если значение столбца "метки времени" для данной строки, прибывающей от ведущего устройства, выше чем это на ведомом устройстве, оно применяется; иначе это не применяется на ведомое устройство. Это иллюстрируется следующим псевдокодом:

if (master_new_column_value > slave_current_column_value)  apply_update();

Эта функция может использоваться для "самого большого разрешения конфликтов" побед метки времени. Этот тип разрешения конфликтов гарантирует, что в случае конфликта версия строки, которая была последний раз обновлена, является версией, которая сохраняется.

Важный

Значение столбца от ведущего устройства "после" изображения используется этой функцией.

NDB$MAX_DELETE_WIN(column_name). Это - изменение на NDB$MAX(). Вследствие того, что никакая метка времени не доступна для удалить работы, удалить использования NDB$MAX() фактически обрабатывается как NDB$OLD. Однако, для некоторых вариантов использования, это не оптимально. Для NDB$MAX_DELETE_WIN(), если значение столбца "метки времени" для данного добавления строки или обновления существующей строки, прибывающей от ведущего устройства, выше чем это на ведомом устройстве, это применяется. Однако, удалите операции, обрабатываются как всегда наличие более высокого значения. Это иллюстрируется в следующем псевдокоде:

if ( (master_new_column_value > slave_current_column_value)        ||      operation.type == "delete")  apply_update();

Эта функция может использоваться для "самой большой метки времени, удалить победы" разрешение конфликтов. Этот тип разрешения конфликтов гарантирует, что в случае конфликта версия строки, которая была удалена или (иначе) последний раз обновлена, является версией, которая сохраняется.

Отметить

Как с NDB$MAX(), значение столбца от ведущего устройства "после" изображения является значением, используемым этой функцией.

NDB$EPOCH(). NDB$EPOCH() функционируйте отслеживает порядок, в котором тиражированные эпохи применяются на ведомый MySQL Cluster относительно изменений, происходящих на ведомом устройстве. Это относительное упорядочивание используется, чтобы определить, параллельны ли изменения, происходящие на ведомом устройстве, с какими-либо изменениями, которые происходят локально, и находятся поэтому потенциально в конфликте.

Большинство того, что следует в описании NDB$EPOCH() также применяется к NDB$EPOCH_TRANS(). Любые исключения отмечаются в тексте.

NDB$EPOCH() асимметрично, работающий на одном MySQL Cluster в круговой конфигурации репликации с двумя кластерами (иногда называемый "активно-активной" репликацией). Мы относимся здесь, чтобы кластеризироваться, на котором это работает как основное устройство, и другой как вторичное устройство. Ведомое устройство на основном устройстве ответственно за обнаружение и обработку конфликтов, в то время как ведомое устройство на secondaryis, не включенном в любое обнаружение конфликта или обработку.

Когда ведомое устройство на основном устройстве обнаруживает конфликты, это вводит события в свой собственный двоичный журнал, чтобы компенсировать их; это гарантирует, что вторичный MySQL Cluster в конечном счете перестраивает себя с основным устройством и так сохраняет основное устройство и вторичное устройство от отклонения. Этот механизм компенсации и перестройки требует, чтобы основной MySQL Cluster всегда выиграл любые конфликты со вторичным устройством — то есть, что изменения основного устройства всегда используются, а не те от вторичного устройства в событии конфликта. Это "основное устройство всегда выигрывает" правило, имеет следующие импликации:

NDB$EPOCH() и NDB$EPOCH_TRANS() не требуйте никаких пользовательских модификаций схемы, или приложение изменяется, чтобы обеспечить обнаружение конфликта. Однако, осторожная мысль должна быть дана схеме, используемой, и используемые схемы доступа, чтобы проверить, что полная система ведет себя в пределах указанных пределов.

Каждый из NDB$EPOCH() и NDB$EPOCH_TRANS() функции могут взять дополнительный параметр; это - число битов, чтобы использовать, чтобы представить более низкие 32 бита эпохи, и должно быть установлено в не меньше, чем

CEIL( LOG2( TimeBetweenGlobalCheckpoints / TimeBetweenEpochs ), 1) 

Для значений по умолчанию этих параметров конфигурации (2000 и 100 миллисекунд, соответственно), это дает значение 5 битов, таким образом, значение по умолчанию (6) должно быть достаточным, если другие значения не используются для TimeBetweenGlobalCheckpoints, TimeBetweenEpochs, или оба. Значение, которое является слишком маленьким, может привести к ложным положительным сторонам, в то время как тот, который является слишком большим, мог привести к чрезмерному потраченному впустую пространству в базе данных.

Оба NDB$EPOCH() и NDB$EPOCH_TRANS() вставьте записи для конфликтных строк в соответствующие таблицы исключений, при условии, что эти таблицы были определены согласно тем же самым правилам схемы таблицы исключений как описано в другом месте в этом разделе (см. NDB$OLD(column_name)). Отметьте, что Вы должны создать любую таблицу исключений прежде, чем составить таблицу, с которой она должна использоваться.

Как с другими функциями обнаружения конфликта, обсужденными в этом разделе, NDB$EPOCH() и NDB$EPOCH_TRANS() активируются включением соответствующих записей в mysql.ndb_replication таблица (см. ndb_replication системная таблица). Роли основного и вторичного MySQL Clusters в этом сценарии полностью определяются mysql.ndb_replication записи таблицы.

Отметить

Поскольку алгоритмы обнаружения конфликта, используемые NDB$EPOCH() и NDB$EPOCH_TRANS() асимметричны, следует использовать различные значения для и вторичного ведомого устройства основного ведомого устройства server_id записи.

NDB$EPOCH() и NDB$EPOCH_TRANS() переменные состояния. Несколько переменных состояния могут использоваться, чтобы контролировать NDB$EPOCH() и NDB$EPOCH_TRANS() обнаружение конфликта. Можно видеть, сколькими строки были найдены в конфликте NDB$EPOCH() так как это ведомое устройство было последнее перезапущенный от текущей стоимости Ndb_conflict_fn_epoch системная переменная состояния.

Ndb_conflict_fn_epoch_trans обеспечивает число строк, которые были найдены непосредственно в конфликте NDB$EPOCH_TRANS(); числом строк, фактически перестроенных, включая тех, на которых влияют из-за их членства в или зависимости от тех же самых транзакций как другие конфликтные строки, дают Ndb_conflict_trans_row_reject_count.

Для получения дополнительной информации см. Раздел 17.3.4.4, "MySQL Cluster Status Variables".

Ограничения на NDB$EPOCH(). Следующие ограничения в настоящий момент применяются при использовании NDB$EPOCH() выполнять обнаружение конфликта:

NDB$EPOCH_TRANS(). NDB$EPOCH_TRANS() расширяется NDB$EPOCH() функция. Конфликты обнаруживаются и обрабатываются, таким же образом используя "основные победы все" правило (см. NDB$EPOCH()) но с дополнительным условием, что любые другие строки, обновленные в той же самой транзакции, в которой произошел конфликт, также расцениваются как являющийся в конфликте. Другими словами, где NDB$EPOCH() перестраивает отдельные конфликтные строки на вторичном устройстве, NDB$EPOCH_TRANS() перестраивает конфликтные транзакции.

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

NDB$EPOCH_TRANS() подчиняется тем же самым условиям и ограничениям как NDB$EPOCH(), и кроме того требует, чтобы двоичные события строки журнала Версии 2 использовались (--log-bin-use-v1-row-events равный 0), который добавляет издержки хранения 2 байтов за событие в двоичном журнале. Кроме того, все ID транзакции должны быть записаны в двоичном журнале вторичного устройства (--ndb-log-transaction-id опция), который добавляет дальнейшие переменные издержки (до 13 байтов за строку).

См. NDB$EPOCH().

NULL. Указывает, что разрешение конфликтов не должно использоваться для соответствующей таблицы.

Информация о статусе. Переменная состояния сервера Ndb_conflict_fn_max обеспечивает количество числа раз, что строка не была применена на текущий узел SQL из-за "самого большого разрешения конфликтов" побед метки времени с прошлого раза, когда mysqld был запущен.

Число раз, что строка не была применена как результат "того же самого разрешения конфликтов" побед метки времени на данном mysqld с прошлого раза, это было перезапущено, дается глобальной переменной состояния Ndb_conflict_fn_old. В дополнение к постепенному увеличению Ndb_conflict_fn_old, первичный ключ строки, которая не использовалась, вставляется в таблицу исключений, как объяснено позже в этом разделе.

Таблица исключений. Использовать NDB$OLD() функция разрешения конфликтов, также необходимо составить таблицу исключений, соответствующую каждому NDB таблица, для которой должен использоваться этот тип разрешения конфликтов. Это - также истина при использовании NDB$EPOCH() или NDB$EPOCH_TRANS(). Имя этой таблицы является именем таблицы, для которой разрешение конфликтов должно быть применено со строкой $EX добавленный. (Например, если имя исходной таблицы mytable, имя соответствующего имени таблицы исключений должно быть mytable$EX.) Эта таблица составляется следующим образом:

CREATE TABLE original_table$EX  (    server_id INT UNSIGNED,    master_server_id INT UNSIGNED,    master_epoch BIGINT UNSIGNED,    count INT UNSIGNED,    original_table_pk_columns,    [additional_columns,]    PRIMARY KEY(server_id, master_server_id, master_epoch, count)) ENGINE=NDB;

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

Отметить

Имена первых четырех столбцов и столбцов, соответствующих столбцы первичного ключа исходной таблицы, не являются критическими; однако, мы предлагаем по причинам ясности и непротиворечивости, что Вы используете имена, показанные здесь для server_id, master_server_id, master_epoch, и count столбцы, и что Вы используете те же самые имена в качестве в исходной таблице для столбцов, соответствующих тем в первичном ключе исходной таблицы.

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

Дополнительные столбцы могут дополнительно быть определены после этих столбцов, но не перед любым из них; любые такие дополнительные столбцы не могут быть NOT NULL. Первичный ключ таблицы исключений должен быть определен как показано. Таблица исключений должна использовать NDB механизм хранения. Пример, который использует NDB$OLD() с таблицу исключений показывают позже в этом разделе.

Важный

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

Примеры. Следующие примеры предполагают, что у Вас уже есть рабочая установка репликации MySQL Cluster, как описано в Разделе 17.6.5, "Подготовка MySQL Cluster for Replication", и Раздела 17.6.6, "Репликация Кластера MySQL Starting (Единственный Канал Репликации)".