Как повторно синхронизировать реплику чтения AWS RDS

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

База данных является базой данных MySQL с таблицами Innodb.

1 ответ

Решение

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

Репликация осуществляется через двоичный журнал ("binlog"), который фиксирует все изменения в мастере. В стандартной асинхронной репликации MySQL - как используется в RDS - реплика имеет два потока, предназначенных для конкретных целей, поток ввода-вывода, который подключается к мастеру и захватывает события репликации из бинарника мастера и записывает их во временную область хранения, которая называется журнал ретрансляции и поток SQL, который читает из журнала ретрансляции и применяет изменения к реплике.

На реплике, запрос SHOW SLAVE STATUS; скажет вам, запущены ли эти два потока, или нет. Если они работают, реплика исправна, хотя она может быть позади мастера, о чем свидетельствует значение Seconds_Behind_Master что вы также найдете в выводе этого запроса. В противном случае вы обнаружите возникшую ошибку, приводящую к остановке одного или других потоков.

Теоретически, реплика MySQL никогда не выйдет из синхронизации, если не произойдет одно из трех:

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

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

Вторая проблема может вызвать проблемы с потоком ввода-вывода или потоком SQL, но они должны быть редкими.

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

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

Это немного сложнее в RDS, потому что у вас нет SUPER привилегия, но это все еще возможно. Еще...

tl; dr: нарушенная репликация - это только симптом - вы должны выяснить, в чем проблема на самом деле.

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

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

Если вы четко понимаете, что пошло не так, вы можете временно сделать реплику доступной для записи (используя настройку группы параметров для read_only системная переменная), внесите исправления и перезапустите репликацию. В RDS вы можете только перезагрузить текущий указатель события, перезагрузив реплику, так как у вас нет SUPER привилегии, или вы можете перевести реплику в состояние, в котором она должна была находиться после репликации проблемного события, а затем использовать обходной путь, который они для этого предоставляют, используя CALL mysql.rds_skip_repl_error();, Не используйте это, не понимая, что он делает - в частности, он игнорирует сбой и переходит к следующему событию, абсолютно оставляя вашу реплику в несовместимом состоянии, если вы вручную не привели реплику в согласованное состояние. Он должен быть зарезервирован только для аварийных ситуаций, когда сохранение текущей реплики важнее, чем сохранение правильной реплики, поскольку пропуск ошибки по существу гарантирует больше ошибок в будущем.

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

Другие вопросы по тегам