Mysql ошибка репликации

Время на прочтение
9 мин

Количество просмотров 4.9K

Настроить репликацию в MySQL просто, но управление ею в продакшне никогда не было легкой задачей. Даже с новым автоматическим позиционированием GTID все может пойти не так, если не знать, что делать. После настройки репликации может произойти всякое. Легко допустить ошибки, которые приведут к катастрофическим последствиям для ваших данных.

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

Настройка репликации

При настройке репликации MySQL необходимо загрузить ведомые (slave) узлы датасетом с ведущего (master) узла. В таких решениях, как Galera cluster, данная операция выполняется автоматически с помощью выбранного вами метода. При репликации MySQL это нужно делать самостоятельно, поэтому, естественно, вы берете стандартный инструмент резервного копирования.

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

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

mysqldump -uuser -ppass --single-transaction --routines --triggers --all-databases > dumpfile.sql

Для проверки того, совпадает ли ваш слейв на 100%, рекомендуется использовать pt-table-checksum после настройки репликации:

pt-table-checksum --replicate=test.checksums --ignore-databases mysql h=localhost,u=user,p=pass

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

Использование неправильного метода репликации

По умолчанию в MySQL использовался так называемый метод командной репликации. Он представляет собой именно то, чем он является: поток репликации каждой команды, выполняемой на мастере, которая будет воспроизводиться на слейве. Поскольку сам MySQL является многопоточным, а его (традиционная) репликация — нет, то порядок выполнения команд в потоке репликации может не совпадать на 100%. Также, повтор команд может дать разные результаты, если они не выполняются в одно и то же время.

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

Ответом MySQL стала так называемая построчная репликация. При построчной репликации данные реплицируются везде, где это возможно, но в некоторых исключительных случаях все же используются команды. Хорошим примером может служить изменение DLL таблицы, где при репликации нужно будет скопировать каждую строку таблицы. Поскольку это неэффективно, такой оператор будет реплицироваться традиционным способом. Когда репликация на основе строк обнаружит дрейф данных, она остановит ведомый поток, чтобы не ухудшить ситуацию.

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

Круговая репликация

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

MySQL репликация Мастер-Мастер 

MySQL репликация Мастер-Мастер 

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

Топология кольцевой репликации в MySQL

Топология кольцевой репликации в MySQL

Кольцевая репликация в MySQL проблематична по следующим причинам: задержка, высокая степень доступности и дрейф данных. При записи некоторых данных на сервер A, они должны проделать три прыжка, чтобы оказаться на сервере D (через серверы B и C). Поскольку (традиционная) репликация MySQL является однопоточной, любой долго выполняющийся запрос в процессе репликации может застопорить все кольцо. Кроме того, если какой-либо из серверов выйдет из строя, то кольцо будет разорвано. В настоящее время не существует программного обеспечения для преодоления отказов, способного восстанавливать структуры кольца. Также может произойти дрейф данных, когда данные записываются на сервер A и в то же время изменяются на сервере C или D.

Нарушенная кольцевая репликация

Нарушенная кольцевая репликация

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

Замедление репликации при больших обновлениях

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

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

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

Для того чтобы это обойти, и MariaDB, и MySQL предлагают параллельную репликацию. Реализация может отличаться в зависимости от производителя и версии. MySQL 5.6 использует параллельную репликацию при условии, что запросы разделены по схемам. MariaDB 10.0 и MySQL 5.7 могут обрабатывать параллельную репликацию по схемам, но при этом имеют иные ограничения. Если вы перегружены записью, то выполнение запросов через параллельные слейв потоки может ускорить процесс репликации. В противном случае лучше придерживаться традиционной однопоточной репликации.

Изменения схемы

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

Часто используется обходной путь — сначала применить изменение схемы к слейв узлам. Для командной репликации такое решение прекрасно подходит, но для построчной — это действует только до определенной степени. Построчная репликация допускает присутствие дополнительных столбцов в конце таблицы, поэтому, пока она записывает первые столбцы, все будет в порядке. Сначала примените изменение ко всем слейвам, затем выполните аварийное переключение на один из них, а потом примените изменение к мастеру и подключите его в качестве слейва. Если ваше изменение включает в себя вставку столбца в середину или его удаление, то это будет выполняться с помощью построчной репликации.

Существуют инструменты, позволяющие выполнять изменения схемы в режиме онлайн более надежно. Percona Online Schema Change (известная как pt-osc) создаст теневую таблицу с новой структурой, вставит новые данные с помощью триггеров и выполнит обратное заполнение данных в фоновом режиме. После создания новой таблицы она просто поменяет старую таблицу на новую внутри транзакции. Это работает не во всех случаях, особенно если в существующей таблице уже есть триггеры.

Альтернативой является новый инструмент Gh-ost от Github. Этот онлайн-инструмент для изменения схемы сначала создаст копию существующего макета таблицы, изменит таблицу в соответствии с новой структурой, а затем подключит этот процесс как реплику MySQL. Он будет использовать поток репликации для поиска новых строк, которые были вставлены в исходную таблицу, и в то же время будет выполнять заполнение таблицы. После завершения заполнения исходная и новая таблицы поменяются местами. Естественно, все операции с новой таблицей также попадают в поток репликации, поэтому на каждой реплике миграция происходит в одно и то же время.

Таблицы памяти и репликация

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

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

Установка переменной read_only в True

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

Есть простое решение: установите переменную read_only в true. Это запретит кому-либо вносить изменения в данные, кроме пользователей репликации и рут-пользователей. Большинство менеджеров по устранению отказов устанавливают этот флаг автоматически, чтобы предотвратить запись пользователей на используемый мастер во время аварийного переключения. Некоторые из них даже сохраняют этот флаг после восстановления работоспособности.

Это все же оставляет возможность рут-пользователю выполнить ошибочный CRUD-запрос на слейве. Чтобы этого не произошло, начиная с версии MySQL 5.7.8 существует переменная super_read_only, которая блокирует обновление данных даже для рут-пользователя.

Активация GTID

При репликации MySQL очень важно запускать слейв с правильной позиции в бинарном логе. Получить эту позицию можно при создании резервной копии (xtrabackup и mysqldump поддерживают это) или когда вы остановили синхронизацию на узле, копию которого вы создаете. Запуск репликации с помощью команды CHANGE MASTER TO будет выглядеть следующим образом:

mysql> CHANGE MASTER TO MASTER_HOST='x.x.x.x',MASTER_USER='replication_user', MASTER_PASSWORD='password', MASTER_LOG_FILE='master-bin.0001', MASTER_LOG_POS=  04;

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

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

Для решения этой проблемы в Oracle и MariaDB был внедрен глобальный идентификатор транзакций (GTID). GTID позволяет автоматически согласовывать слейвы, и как в MySQL, так и в MariaDB сервер сам определяет правильное положение. Однако в обоих случаях GTID реализован по-разному, и поэтому они несовместимы. Если вам нужно обеспечить репликацию с одного сервера на другой, то она должна быть настроена с традиционным позиционированием бинарного лога. Кроме того, программное обеспечение для преодоления отказов должно быть предупреждено о том, что не следует использовать GTID.

Заключение

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

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


Материал подготовлен в рамках специализации «Administrator Linux». Если вам интересно узнать подробнее о формате обучения и программе, познакомиться с преподавателем курса — приглашаем на день открытых дверей онлайн. Регистрация здесь.

В процессе длительной работы с двумя и более MySQL баз данных, между которым происходит репликация, можно столкнуться с массой мелких ошибок, вызванных, например, конфликтами первичных ключей, повреждениями журналов и т.п. Особенно, если репликация настроена, как мастер-мастер, конфликты гарантированы. Естественно, из-за мелких ошибок никто не станет полностью заново синхронизировать две базы данных, а скорее всего, пропустит ошибку через установку SQL_SLAVE_SKIP_COUNTER или slave-skip-errors. Со временем, две БД накопят некий запас неконсистентности, благодаря таким пропущенным конфликтам. Итак, что делать, если нужно восстановить полную консистентность, или в случае, когда ошибка в репликации совсем критичная и не решается вышеописанными способами? Единственный выход — полная синхронизация двух БД «с нуля» и сброс состояния репликации.

Порядок действий таков — на мастере:

mysql-master> STOP SLAVE;
mysql-master> RESET MASTER;
mysql-master> FLUSH TABLES WITH READ LOCK;
mysql-master> SHOW MASTER STATUS;
+------------+----------+--------------------+------------------------+---------------+--------+--------------+---------------+
| File           | Position | Binlog_Do_DB | Binlog_Ignore_DB  |  bin.000002 |     654 |                    | mysql            |
+------------+----------+--------------------+------------------------+---------------+--------+--------------+----------------+

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

Далее, не закрывая соединения с мастер базой (т.к. это снимет режим только чтения), делаем дамп всех необходимых данных:

 [user@master ~]$ mysqldump -uroot -p --all-database > ./mysqldump.sql 

Теперь можно снять режим чтения командой

mysql-master> UNLOCK TABLES;

Следующий шаг — скопировать дамп на слейв сервер и выполнить там:

mysql-slave> STOP SLAVE; 

Импортируем загруженный с мастер сервера дамп:

[user@slave1 ~]$ mysql -uroot -p < mysqldump.sql span="">

Далее на слейве удаляем все журналы от мастера и начинаем репликацию с момента, когда на мастере был сделан дамп:

mysql-slave> RESET SLAVE;
mysql-slave> CHANGE MASTER TO MASTER_LOG_FILE = [записанный ранее File], MASTER_LOG_POS =[записанный ранее Position];
mysql-slave> START SLAVE;
mysql-slave> SHOW SLAVE STATUS;

Убеждаемся в том, что параметры Slave_IO_Running и Slave_SQL_Running установлены в Yes. В случае, если у вас мастер-мастер репликация, продолжаем на слейв сервере:

mysql-slave> STOP SLAVE;
mysql-slave> FLUSH TABLES WITH READ LOCK;
mysql-slave> RESET MASTER;
mysql-slave> SHOW MASTER STATUS;+------------+----------+--------------+------------------+
| File       | Position | Binlog_Do_DB | Binlog_Ignore_DB |
+------------+----------+--------------+------------------+
| bin.000006 |       12 |              | mysql            |
+------------+----------+--------------+------------------+

Снова запоминаем File и Position и на мастер сервере делаем:

mysql-master> CHANGE MASTER TO MASTER_LOG_FILE=[записанный File], MASTER_LOG_POS=[записанный Position];
mysql-master> START SLAVE;
mysql-master> SHOW SLAVE STATUS G;

Убеждаемся в том, что параметры Slave_IO_Running и Slave_SQL_Running установлены в Yes.

На слейве снимаем лок и запускаем репликацию:

mysql-slave> UNLOCK TABLES;
mysql-slave> START SLAVE;

Подробнее о настройке мастер-мастер репликации с нуля можно прочитать

— See more at: http://www.sover.pro/blogs/54-sinhronizaciya-mysql-baz-posle-oshibki-replikacii.html#sthash.uf9cRY0w.dpu

 
Ошибка «Error 1292: Incorrect date / datetime value» при синхронизации
Суть проблемы: чаще всего такая ошибка возникает при попытке синхронизации с таблицей, в которой есть запись со значением ‘0000-00-00’ или ‘0000-00-00 00:00:00’ в полях типа DATE или DATETIME соответственно. В некоторых случаях настройки MySQL позволяют создавать такие записи, но не позволяют редактировать схему таблицы.

Решение: вообще, при синхронизации или экспорте данных MySQL Workbench добавляет специальные запросы, как бы оборачивая основной SQL код:

invalid-dates-solution

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

SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='TRADITIONAL,ALLOW_INVALID_DATES';
...
SET SQL_MODE=@OLD_SQL_MODE;

Ошибка «Error 1005: Can’t create table ‘…’ (errno: 150)» при синхронизации
Суть проблемы: обычно эта ошибка касается неправильной настройки внешних ключей (вкладка «Foreign Keys» в настройках таблиц). У меня она возникала в том случае, если я делал ключом поле с меткой NOT NULL, а в поведении внешнего ключа указывал SET NULL — это абсурд, ведь InnoDB не сможет установить значение NULL в поле, где такое значение запрещено.

Решение: внимательно следим за настройкой поведения внешних ключей. Если необходимо поведение SET NULL, у поля-ключа в дочерней таблице не должен стоять флаг NOT NULL.
Ошибка «Field … can not be null» при выгрузке стартовых данных
Суть проблемы: независимо от настроек таблицы, все поля в «Inserts» имеют по умолчанию значение NULL, даже если такое значение не разрешено для данного поля. Соответственно, при выгрузке на сервер может возникнуть ошибка.

Решение: при добавлении стартовых данных следим за тем, чтобы значение NULL оставалось лишь в тех полях, где это разрешено. Если нужно сделать поле пустой строкой, делаем финт ушами: ставим в него курсор, нажимаем пробел, затем стираем его (во всяком случае, я не придумал ничего получше на такой случай :)).
Ошибка Сan’t connect to MySQL server on … (10061) при подключении
Суть проблемы: говорят, что может быть несколько причин. Я встечал такую ошибку в случае, если в файле my.cnf была установлена настройка «skip-networking» — по сути она не даёт MySQL работать с сетью.

Решение: закомментировать данную опцию:

 

Поиск неисправностей репликации

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

  • Производит ли головной сервер записи в двоичный журнал? Проверьте это при помощи команды SHOW MASTER STATUS. Если да, значение Position будет отличным от нуля. Если нет, проверьте, запущен ли головной сервер с опцией log-bin и установлен ли server-id.

  • Запущен ли подчиненный сервер? Проверьте это при помощи команды SHOW SLAVE STATUS. Ответ находится в столбце Slave_running. Если нет, проверьте опции подчиненного сервера и просмотрите сообщения в журнале ошибок.

  • Если подчиненный сервер запущен, установил ли он соединение с головным сервером? Выполните команду SHOW PROCESSLIST, найдите поток, которому соответствует значение system user в столбце User и none в столбце Host, и проверьте столбец State. Если в нем находится значение connecting to master, проверьте привилегии для пользователя репликации на головном сервере, имя хоста головного сервера, установку DNS, посмотрите, запущен ли головной сервер в текущее время, доступен ли он для подчиненного сервера. После этого, если все окажется в порядке, просмотрите журналы ошибок.

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

  • Если запрос, успешно выполняемый на головном сервере, не выполняется на подчиненном, и нельзя выполнить полную ресинхронизацию базы данных (ее стоит выполнить), попробуйте сделать следующее:

    • Сначала проверьте: возможно где-либо случайно оказалась ненужная запись. Разберитесь, как она оказалась там, затем удалите ее, и выполните команду SLAVE START.

    • Если вы проделали все, о чем написано выше, и ничего не помогло или этого сделать нельзя, попытайтесь понять, будет ли безопасно выполнить обновления вручную (если необходимо) и после этого игнорировать следующий запрос от головного сервера.

    • Если вы решили пропустить следующий запрос, выполните команды SET GLOBAL SQL_SLAVE_SKIP_COUNTER=1; SLAVE START; чтобы пропустить запрос, не использующий функции AUTO_INCREMENT или LAST_INSERT_ID(). В противном случае выполните команды SET GLOBAL SQL_SLAVE_SKIP_COUNTER=2; SLAVE START. Причина того, что запросы, использующие функции AUTO_INCREMENT или LAST_INSERT_ID(), обрабатываются по-другому, заключается в том, что они создают два события в двоичном журнале головного сервера.

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

  • Удостоверьтесь, что вы не внесли старой ошибки при апгрейде MySQL до более новой версии.

  • Если ничего не помогает, просмотрите журналы ошибок. Если журналы большие, выполните команду grep -i slave /path/to/your-log.err на подчиненном сервере. Искать ошибку на головном сервере — не лучшая идея, поскольку в его журналах находятся лишь системные ошибки общего характера; если это возможно, он посылает ошибку на подчиненный сервер, когда что-либо происходит не так, как надо.

Если вы убедились, что пользовательская ошибка здесь ни при чем, однако механизм репликации по-прежнему не работает или работает нестабильно, пришло время начать работу над отчетом об ошибке. Вы должны предоставить нам столько информации, сколько нужно, чтобы отследить ошибку. Пожалуйста, уделите отчету об ошибке нужное количество времени и усилий, чтобы сделать его хорошо. В идеале мы хотели бы иметь контрольный пример в формате, который находится в каталоге mysql-test/t/rpl* исходного дерева. Отослав такой контрольный пример, в большинстве случаев можно рассчитывать на получение патча в течение одного-двух дней, хотя, конечно, это время может варьироваться в зависимости от множества факторов.

Еще один хороший способ проинформировать нас об ошибке — написать простую программу с легко конфигурируемыми параметрами соединения для головного и подчиненного серверов, в которой будет продемонстрирована проблема наших систем. Программа может быть написана на Perl или на C, в зависимости от того, какой язык вы знаете лучше.

Подготовив информацию об ошибке одним из двух способов, используйте утилиту mysqlbug, чтобы создать отчет об ошибке, и пошлите его по адресу <bugs@lists.mysql.com>. Если же вы имеете дело с фантомом — проблемой, которая имеет место, но вы по какой-либо причине не можете ее воспроизвести по желанию:

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

  • Запустите подчиненный сервер с опциями log-slave-updates и log-bin — при этом в журнал будет заноситься информация обо всех обновлениях, происходящих на подчиненном сервере.

  • Сохраните все доказательства наличия ошибки перед сбросом репликации. Если у нас нет информации о проблеме, или имеется только отрывочная информация, потребуется время, чтобы найти источник проблемы. Вы должны собрать следующие «свидетельства»:

    • Все двоичные журналы головного сервера

    • Весь двоичный журнал подчиненного сервера

    • Вывод команды SHOW MASTER STATUS на головном сервере во время обнаружения проблемы

    • Вывод команды SHOW SLAVE STATUS на головном сервере во время обнаружения проблемы

    • Журналы ошибок головного сервера и подчиненного сервера

  • Для изучения двоичных журналов используйте утилиту mysqlbinlog. Таким образом можно находить проблемные запросы, например:

    mysqlbinlog -j pos_from_slave_status /path/to/log_from_slave_status | head
    

Собрав «свидетельства» о проблеме-фантоме, попробуйте сначала организовать их в отдельный контрольный пример. После этого сообщите о проблеме по адресу <bugs@lists.mysql.com>, описав эту проблему во всех подробностях.

Содержание

1032

Last_SQL_Error: Could not execute Update_rows event on table databaseName.TableName; Can't find record in 'TableName', Error_code: 1032; handler error HA_ERR_KEY_NOT_FOUND; the even
t's master log mysql-bin.021084, end_log_pos 696352185

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

SET GLOBAL SQL_SLAVE_SKIP_COUNTER = 1; start slave;
 
show slave statusG

Следует иметь ввиду, что подобное поведение не является нормой. Нужно устранить проблему при возможности.

В percona toolkit имеется утилита, которая позволяет забивать на эту ошибку и ехать дальше — pt-slave-restart. При выполнении тулза сообщает нам, в каком месте bin-log она встретила ошибку и едет дальше.

# Выполняется на SLAVE
 
pt-slave-restart 
 
# A software update is available:
2022-08-18T20:43:29  SRV-SLAVE-relay-bin.000417   282849405 1032 
2022-08-18T20:43:29  SRV-SLAVE-relay-bin.000417   283282377 1032 
^CExiting on SIGINT.

Можно попытаться посмотреть запрос, который эту ошибку вызывает, используя утилиту mysqlbinlog

# -j - начальная позиция лога
# --stop-position - место, до куда смотреть ( в нашем случае величины совпадают, смотрим только эту запись)
mysqlbinlog -s -j 283282377  --stop-position=283282377  /var/lib/mysql/SRV-SLAVE-relay-bin.000417

pt-table-checksum

Также можно попытаться найти разницу между мастером и слейвом, используя команду pt-table-checksum
Для этого добавляем пользователя MySQL root на SLAVE с возможностью доступа снаружи:

##
# Добавляем пользователя MySQL
CREATE USER 'root'@'%' IDENTIFIED BY '$Password';
GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' WITH GRANT OPTION;
FLUSH PRIVILEGES;
##
# Считаем расхождение:
# pt-table-checksum --no-check-binlog-format --nocheck-replication-filters
 
pt-table-checksum --nocheck-replication-filters --replicate=testdb.checksums 
 --databases=testdb  h=149.202.XXX.XXX,u=root,p=$Password,P=3306 --no-check-binlog-format 
# Смотрим результат
Checking if all tables can be checksummed ...
Starting checksum ...
Diffs cannot be detected because no slaves were found.  Please read the --recursion-method documentation for information.
            TS ERRORS  DIFFS     ROWS  DIFF_ROWS  CHUNKS SKIPPED    TIME TABLE
08-24T23:33:54      0      0        5          0       1       0   0.025 testdb.Persons
mysql> show variables like 'binlog_format';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| binlog_format | ROW   |
+---------------+-------+
1 row in set (0.00 sec)

Обновлено Обновлено: 24.07.2019
Опубликовано Опубликовано: 2016 год или раньше

Если кластер работает в режиме Master — Master, сначала найдем ноду, на которой произошел сбой репликации. Для этого заходим на каждом сервере в оболочку mysql следующей командой:

# mysql -uroot -p

* в данном примере заходим от имени пользователя root.

И выводим состояние ноды в режиме Slave:

mysql> SHOW SLAVE STATUSG

В случае проблем с репликацией мы увидим значения Slave_IO_Running и/или Slave_SQL_Running в состоянии No, а также описание ошибки:

Состояние нерабочей репликации MySQL

На рабочей Master-ноде

Блокируем все таблицы всех баз для чтения и записи:

mysql> FLUSH TABLES WITH READ LOCK; SET GLOBAL read_only = ON;

И выводим состояние работы СУРБД:

mysql> show master statusG

Результат будет, примерно, таким:

            File: mysql-bin.000015
        Position: 6315
    Binlog_Do_DB:
Binlog_Ignore_DB: information_schema,mysql

Запомним или запишем значения для File и Position. Они понадобятся при восстановлении вторичной ноды кластера.

Теперь выходим из командной оболочки базы:

mysql> q

и создаем дамп рабочих баз:

# mysqldump -uroot -p -v —databases db1 db2 > /tmp/mydb_dump.sql

* данная команда сделает дамп баз db1db2 и сохранит его в файл /tmp/mydb_dump.sql.

Теперь снова подключаемся к MySQL:

# mysql -uroot -p

и снимаем ранее установленные блокировки:

mysql> SET GLOBAL read_only = OFF;

Отключаемся:

mysql> q

Полученный ранее файл с резервной копией переносим на второй сервер при помощи такой команды:

# scp /tmp/mydb_dump.sql dmosk@192.168.166.156:/tmp

* в данном примере, мы скопируем созданный нами дамп /tmp/mydb_dump.sql в каталог /tmp сервера 192.168.166.156 подключившись под учетной записью dmosk.

На нерабочей ноде

Создаем дамп баз:

# mysqldump -uroot -p -v —databases db1 db2 > /tmp/mydb_dump_slave.sql

Заходим в оболочку управления MySQL:

# mysql -uroot -p

Останавливаем репликацию:

mysql> stop slave;

Удаляем старые базы:

mysql> drop database db1;

mysql> drop database db2;

* в данном примере удаляются базы, для которых мы сделали резервные копии.

И создаем их заново:

mysql> CREATE DATABASE db1 DEFAULT CHARACTER SET utf8 DEFAULT COLLATE utf8_general_ci;

mysql> CREATE DATABASE db2 DEFAULT CHARACTER SET utf8 DEFAULT COLLATE utf8_general_ci;

Выходим из оболочки:

mysql> q

Теперь восстанавливаем базы из ранее созданного дампа:

# mysql -v -uroot -p < /tmp/mydb_dump.sql

… или если создавалась резервная копия для одной базы, команда будет с указанием этой базы:

# mysql -v -uroot -p db < /tmp/mydb_dump.sql

Опять подключаемся к СУБД:

# mysql -uroot -p

и вводим такую команду:

mysql> change master to master_host = «192.168.166.155», master_user = «replmy», master_password = «password», master_log_file = «mysql-bin.000015», master_log_pos = 6315;

192.168.166.155: IP-адрес моего первого сервера. replmy: учетная запись для репликации, которая была создана при создании кластера. password: пароль для учетной записи replmymysql-bin.000015: имя файла, которое мы должны были записать или запомнить (у вас может быть другим). 6315: номер позиции, с которой необходимо начать репликацию (также должны были записать или запомнить ранее).

Запускаем репликацию следующей командой:

mysql> start slave;

И проверяем состояние репликации:

mysql> SHOW SLAVE STATUSG

Состояние Slave_IO_Running и Slave_SQL_Running должно быть Yes, а ошибки должны исчезнуть:

Состояние восстановленной репликации MySQL

I already wrote about some MySQL Error Messages which are confusing, here is one more:

080603 20:53:10 [Note] Slave: connected to master ‘[email protected]:3306’,replication resumed in log ‘master-bin.003676’ at position 444286437

080603 20:53:10 [Note] Slave: received end packet from server, apparent master shutdown:

080603 20:53:10 [Note] Slave I/O thread: Failed reading log event, reconnecting to retry, log ‘master-bin.003676’ position 444292333

080603 20:53:10 [Note] Slave: connected to master ‘[email protected]:3306’,replication resumed in log ‘master-bin.003676’ at position 444292333

080603 20:53:10 [Note] Slave: received end packet from server, apparent master shutdown:

080603 20:53:10 [Note] Slave I/O thread: Failed reading log event, reconnecting to retry, log ‘master-bin.003676’ position 444294573

080603 20:53:10 [Note] Slave: connected to master ‘[email protected]host.com:3306’,replication resumed in log ‘master-bin.003676’ at position 444294573

080603 20:53:10 [Note] Slave: received end packet from server, apparent master shutdown:

080603 20:53:10 [Note] Slave I/O thread: Failed reading log event, reconnecting to retry, log ‘master-bin.003676’ position 444298239

080603 20:53:10 [Note] Slave: connected to master ‘[email protected]:3306’,replication resumed in log ‘master-bin.003676’ at position 444298239

After setting up new slave Server I’m getting error log file flooded with messages like this and there is no hint in the message what would explain what is wrong.

In fact the issue in this case is (because of configuration error) two slave servers got the same server-id.

Seriously in this case Master clearly sees the problem in this case as there are 2 servers with same server-id connected and replicating so it should report it to the slave instead of sending end packet.

At very least it would be nice to include possible reason for this error message which MySQL already does in many other cases.

I’ve now filed it as a bug.

Понравилась статья? Поделить с друзьями:
  • Mysql ошибка при запуске приложения 0xc000007b
  • Mysql ошибка кодировки
  • Mysql ошибка unable to connect to localhost
  • Mysql ошибка insert
  • Mysql ошибка error 1064