4.10.4 Возможности репликации и известные проблемы
Ниже приводится список поддерживаемых и не поддерживаемых при репликации
функций:
Реплицирование будет выполнено правильно при использовании значений
AUTO_INCREMENT, LAST_INSERT_ID() и TIMESTAMP.
Если в обновлениях присутствует функция RAND(), реплицирование будет
выполнено некорректно. При реплицировании обновлений с функцией RAND()
применяйте RAND(some_non_rand_expr). В качестве аргумента
(some_non_rand_expr - некоторое не случайное выражение) для функции
RAND() можно, например, использовать функцию UNIX_TIMESTAMP().
На головном и подчиненном серверах следует использовать одинаковый
набор символов (--default-character-set). В противном случае могут
возникать ошибки дублирующихся ключей на подчиненном сервере,
поскольку ключ, который считается уникальным на головном сервере,
может не быть таковым при использовании другого набора символов.
В MySQL 3.23 команда LOAD DATA INFILE будет выполнена корректно, если
файл во время выполнения обновления будет находиться на головном
сервере. Команда LOAD LOCAL DATA INFILE будет проигнорирована. В MySQL
4.0 это ограничение не присутствует - все разновидности команды LOAD
DATA INFILE реплицируются правильно.
Запросы на обновление, в которых используются пользовательские
переменные, являются не безопасными для репликации (пока).
Команды FLUSH не записываются в двоичный журнал и поэтому не
копируются на подчиненный сервер. Проблем при этом не возникает,
поскольку команды FLUSH ничего не изменяют. Однако это означает, что
при непосредственном, без использования оператора GRANT, обновлении
таблиц привилегий MySQL и при последующем реплицировании базы данных
привилегий mysql нужно выполнить команду FLUSH PRIVILEGES на
подчиненных серверах, чтобы новые привилегии вступили в силу.
Временные таблицы, начиная с версии 3.23.29, реплицируются корректно,
за исключением случая, когда при прекращении работы подчиненного
сервера (не только потока подчиненного сервера) некоторые временные
таблицы остаются открытыми и используются в последующих обновлениях.
Для решения этой проблемы перед прекращением работы подчиненного
сервера выполните команду SLAVE STOP, проверьте, чтобы переменная
Slave_open_temp_tables содержала значение 0, затем выполните
mysqladmin shutdown. Если значение переменной Slave_open_temp_tables
не 0, перезапустите поток подчиненного сервера при помощи команды
SLAVE START и проверьте, не улучшилась ли ситуация теперь. Эта
проблема будет решаться более изящно, но придется подождать MySQL 4.0.
В более ранних версиях при использовании временных таблиц репликации
не выполняются должным образом - в таких случаях мы рекомендуем либо
обновить версию MySQL, либо перед выполнением запросов, использующих
временные таблицы, выполнить команду SET SQL_LOG_BIN=0 на своих
клиентах.
MySQL поддерживает лишь один головной и много подчиненных серверов. В
4.x будет добавлен алгоритм голосования, обеспечивающий автоматическое
изменение головного сервера, если что-либо будет выполняться
неправильно при текущем головном сервере. Будут также введены процессы
'агента', которые помогут выполнять распределение нагрузки путем
посылки запросов на выборки различным подчиненным серверам.
Начиная с версии 3.23.26 стало безопасно соединять серверы
циклическими соединениями головной-подчиненный с включенной опцией
log-slave-updates. Однако обратите внимание: при таком способе
установки многие запросы не будут выполняться корректно, если только в
коде вашего клиента не предусмотрена обработка потенциальных проблем,
которые могут случаться при обновлениях, происходящих в различной
последовательности на различных серверах. Это означает, что если вы
сделаете установку следующим образом:
A - > B > - C - > A
то такая установка будет работать только в том случае, если
выполняются непротиворечивые обновления между таблицами. Другими
словами, при вставке данных на серверах A и C нельзя вставлять на
сервере A строку, которая может иметь ключ, противоречащий строке,
вставляемой на сервере C. Также нельзя обновлять одинаковые строки на
двух серверах, если имеет значение порядок обновлений. Обратите
внимание: в версии 3.23.26 изменился формат журнала. Таким образом,
если версия подчиненного сервера меньше 3.23.26, сервер не сможет
считывать записи из журнала.
Если запрос на подчиненном сервере вызывает ошибку, поток подчиненного
сервера завершится, и в файле `.err' появится соответствующее сообщение.
После этого нужно будет вручную установить соединение с подчиненным
сервером, исправить причину ошибки (например обращение к
несуществующей таблице) и затем выполнять SQL-команду SLAVE START
(доступна в версии 3.23.16). При использовании версии 3.23.15
потребуется перезапустить сервер.
Если соединение с головным сервером прервется, подчиненный сервер
попытается сразу же восстановить его, и затем в случае неудачи будет
повторять попытки через установленное в опции master-connect-retry
количество секунд (по умолчанию 60). По этой причине безопасно
выключить головной сервер и после этого перезапустить его через
некоторое время. Подчиненный сервер будет также разрешать проблемы,
возникающие при аварийных отключениях электричества в узлах сети.
Завершение работы подчиненного сервера (корректное) также является
безопасным, поскольку при этом отслеживаются события начиная от
момента остановки сервера. Но в случае некорректного отключения
сервера могут возникать проблемы, особенно, если дисковый кэш не был
синхронизирован перед ``смертью'' системы. Для того чтобы значительно
повысить эффективность своей системы обеспечения отказоустойчивости,
целесообразно приобрести хороший UPS (источник бесперебойного
питания).
Если головной сервер слушает нестандартный порт, это нужно будет
указать также в параметре master-port в файле `my.cnf'.
В версии 3.23.15 все таблицы и базы данных могут быть реплицированы.
Начиная с версии 3.23.16 появилась возможность ограничить репликацию
набором баз данных при помощи директив replicate-do-db в файле `my.cnf';
можно также исключить набор баз данных из репликации при помощи
директив replicate-ignore-db. Обратите внимание,: в версиях MySQL до
3.23.23, имелась ошибка, из-за которой команда LOAD DATA INFILE
выполнялась некорректно, если она применялась к базе данных,
исключенной из репликации.
Начиная с версии 3.23.16 команда SET SQL_LOG_BIN = 0 будет выключать
ведение записей о репликации в журналах (двоичных) на головном
сервере, а команда SET SQL_LOG_BIN = 1 - включать такое ведение
записей. Для выполнения этих команд нужно иметь привилегию SUPER (в
MySQL 4.0.2 и выше) или PROCESS (в более ранних версиях MySQL).
Начиная с версии 3.23.19 можно убрать мусор, оставшийся после
неоконченной репликации (если ее выполнение пошло не должным образом),
и начать все сначала, используя команды FLUSH MASTER и FLUSH SLAVE. В
версии 3.23.26 эти команды переименованы в RESET MASTER и RESET SLAVE
соответственно - чтобы сделать понятным их назначение. Тем не менее,
старые варианты FLUSH все еще работают - для обеспечения
совместимости.
Начиная с версии 3.23.23 можно заменять головные серверы и
корректировать точку положения в журнале репликации при помощи команды
CHANGE MASTER TO.
Начиная с версии 3.23.23 можно при помощи опции binlog-ignore-db
уведомлять головной сервер о том, что обновления в некоторых базах
данных не должны отражаться в двоичном журнале.
Начиная с версии 3.23.26, можно использовать опцию
replicate-rewrite-db для уведомления подчиненного сервера о том, что
он должен применить обновления базы данных на головном сервере к базе
данных с другим именем на подчиненном сервере.
Начиная с версии 3.23.28 можно использовать команду PURGE MASTER LOGS
TO 'имя-журнала', чтобы избавиться от старых журналов без завершения
работы подчиненного сервера.
Из-за того, что по своей природе таблицы MyISAM являются
нетранзакционными, может случиться так, что запрос обновит таблицу
только частично и возвратит код ошибки. Это может произойти, например,
при вставке нескольких строк, одна из которых нарушает ограничение
ключа, или в случае, когда длинный запрос обновления ``убивается''
после обновления некоторых строк. Если такое случится на головном
сервере, поток подчиненного сервера завершит работу и будет ждать,
пока администратор базы данных не примет решение о том, что делать в
этом случае (если только код ошибки не является легитимным и в
результате выполнения запроса не будет сгенерирована ошибка с тем же
кодом). Если такой способ проверки правильности кода ошибки
нежелателен, начиная с версии 3.23.47, некоторые (или все) ошибки
могут быть замаскированы при помощи опции slave-skip-errors.
Отдельные таблицы могут исключаться из репликации при помощи опции
replicate-do-table/replicate-ignore-tab или опции
replicate-wild-do-table/replicate-wild-ignore-table. Однако в
настоящее время наличие определенных конструктивных неточностей в
некоторых довольно редких случаях может приводить к неожиданным
результатам. Протокол репликации явно не уведомляет подчиненный сервер
о том, какие таблицы должны быть изменены запросом, поэтому
подчиненному серверу требуется анализировать запрос, чтобы узнать это.
Чтобы избежать лишнего синтаксического анализа, для которого требуется
прерывать выполнение запросов, исключение таблицы в настоящее время
реализуется путем посылки запроса к стандартному анализатору MySQL для
упрощенного синтаксического анализа. Если анализатор обнаружит, что
таблица должна игнорироваться, выполнение запроса будет остановлено и
выдано сообщение об успехе. Этот подход несколько неэффективен, при
его применении чаще возникают ошибки и, кроме того, имеются две
известные ошибки в версии 3.23.49. Первая может возникнуть из-за того,
что поскольку анализатор автоматически открывает таблицу при анализе
некоторых запросов, игнорируемая таблица должна существовать на
подчиненном сервере. Другая ошибка заключается в том, что при
частичном обновлении игнорируемой таблицы поток подчиненного сервера
не заметит, что таблица должна игнорироваться, и приостановит процесс
репликации. Несмотря на то что вышеупомянутые ошибки концептуально
очень просто исправить, для этого придется изменить достаточно много
кода, что поставит под угрозу состояние стабильности ветви 3.23. Если
описанные случаи непосредственно имеют отношение к вашему приложению
(а это довольно редкий случай) - используйте опцию slave-skip-errors,
чтобы дать указание серверу продолжать репликации, игнорируя эти
ошибки.