MySQL Slave застрял на одном журнале бина + позиция бина журнала на 17+ часов

tl;dr: Репликация остановлена ​​на определенном бинлоге и позиции, и я не знаю почему


У меня есть настройка репликации MySQL с MySQL 5.5.

Эта настройка репликации никогда не отставала и всегда была надежной.

Этим утром я заметил, что Раб отстает от Мастера на 17 часов.

Проводя дополнительные исследования, похоже, проблема с SQL_Thread.

Текущий главный файл журнала, в соответствии с ведомым (через SLAVE STATUS), является mysql-bin.001306 @ позиция 20520499, Это соответствует MASTER STATUS вывод от мастера.

Тем не мение, SLAVE STATUS показывает, что Relay_Master_Log_File Сейчас mysql-bin.001302 с Exec_Master_Log_Pos из 36573336, Relay_Master_Log_File ни Exec_Master_Log_Pos продвинулся вообще, пока я следил за ними сегодня утром.

Глядя в binlogs на master, это заявление, расположенное на mysql-bin.001302@3657336:

# at 36573053
#170221 14:33:48 server id 1  end_log_pos 36573130      Query   thread_id=96205677      exec_time=0     error_code=0
SET TIMESTAMP=1487716428/*!*/;
BEGIN
/*!*/;
# at 36573130
# at 36573213
#170221 14:33:48 server id 1  end_log_pos 36573213      Table_map: `database-name`.`table-name` mapped to number 5873
#170221 14:33:48 server id 1  end_log_pos 36573309      Write_rows: table id 5873 flags: STMT_END_F
### INSERT INTO `database-name`.`table-name`
### SET
###   @1='xxxxxxxx'
###   @2=6920826
###   @3='xxxxxxxx'
###   @4='GET'
###   @5='address'
###   @6=2017-02-21 14:40:24
###   @7=2017-02-21 14:40:24
# at 36573309
#170221 14:33:48 server id 1  end_log_pos 36573336      Xid = 1668637037
COMMIT/*!*/;
# at 36573336

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

mysql> insert into tmp_table ( select <rows> from origin table ); -- 44 million rows
mysql> insert into dest_table ( select * from tmp_table ); -- 44 million rows

В двух рассматриваемых таблицах не было первичного или уникального ключа, что, как я читал, могло быть проблемой. Однако, хотя база данных + таблица, показанная в записи binlog выше, является здесь таблицей назначения - показанная запись вставки не была сгенерирована во время миграции.

Если вы зашли так далеко, вы заслуживаете интернет-очков.

На данный момент, я не уверен, что еще нужно рассмотреть или где еще искать, чтобы найти причину остановки журнала. Любое понимание приветствуется.

Благодарю.


Для справки, вот MASTER STATUS а также SLAVE STATUS вывод на момент публикации:

МАСТЕР СТАТУС

mysql> show master status;
+------------------+----------+--------------+------------------+
| File             | Position | Binlog_Do_DB | Binlog_Ignore_DB |
+------------------+----------+--------------+------------------+
| mysql-bin.001306 | 20520499 |              |                  |
+------------------+----------+--------------+------------------+
1 row in set (0.00 sec)

СТАТУС РАБА

mysql> show slave status \G
*************************** 1. row ***************************
               Slave_IO_State: Waiting for master to send event
                  Master_Host: master-host
                  Master_User: replication-user
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: mysql-bin.001306
          Read_Master_Log_Pos: 20520499
               Relay_Log_File: relay-bin.002601
                Relay_Log_Pos: 36573482
        Relay_Master_Log_File: mysql-bin.001302
             Slave_IO_Running: Yes
            Slave_SQL_Running: Yes
              Replicate_Do_DB:
          Replicate_Ignore_DB:
           Replicate_Do_Table:
       Replicate_Ignore_Table:
      Replicate_Wild_Do_Table:
  Replicate_Wild_Ignore_Table:
                   Last_Errno: 0
                   Last_Error:
                 Skip_Counter: 0
          Exec_Master_Log_Pos: 36573336
              Relay_Log_Space: 3565987462
              Until_Condition: None
               Until_Log_File:
                Until_Log_Pos: 0
           Master_SSL_Allowed: No
           Master_SSL_CA_File:
           Master_SSL_CA_Path:
              Master_SSL_Cert:
            Master_SSL_Cipher:
               Master_SSL_Key:
        Seconds_Behind_Master: 63435
Master_SSL_Verify_Server_Cert: No
                Last_IO_Errno: 0
                Last_IO_Error:
               Last_SQL_Errno: 0
               Last_SQL_Error:
  Replicate_Ignore_Server_Ids:
             Master_Server_Id: 1
1 row in set (0.00 sec)

1 ответ

Решение

Я был на правильном пути здесь с большими транзакциями запроса со вчерашнего дня.

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

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

Из-за того, как работает репликация на основе ROW, подчиненное устройство вместо выполнения идентичного оператора DELETE, которое было выполнено на главном сервере, выполняет оператор DELETE для каждой строки, что в итоге выглядит примерно так:

DELETE FROM table WHERE colA=foo AND colB=bar AND colC=baz....etc

И, поскольку нет индекса, соответствующего этому запросу, однопотоковый поток SQL-репликации выполнил 40 миллионов + операторов удаления (или... пытался), на выполнение которых потребовалось много времени из-за всех проверок, которые должны были быть выполнены. сделано для идентификации каждой строки (в то время таблица имела размер около 80 миллионов строк).

В конце концов я справился с этим, остановив подчиненную нить (STOP SLAVE) пропуск одной подчиненной транзакции (SET GLOBAL sql_slave_skip_counter = 1;) и перезапуск ведомой нити (START SLAVE).

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

mysql> CREATE TABLE table_tmp; -- with the same schema as 'table' (SHOW CREATE TABLE table;)
mysql> RENAME TABLE table TO table_bak, table_tmp TO table;
mysql> INSERT INTO table ( SELECT * FROM table_bak );
mysql> DROP TABLE table_bak;

Поскольку УДАЛЕНИЕ было выполнено на Мастере, ВСТАВКА здесь вставила только те записи, которые я хотел сохранить (удаленные исчезли). И поскольку репликация на основе строк вставляет каждую строку отдельно, а не выполняет один и тот же оператор INSERT INTO...SELECT, в ведомой таблице были заполнены только нужные данные. Затем последующий оператор DROP TABLE удаляет таблицу на ведомом устройстве, не обращаясь к каждой строке отдельно.

Предостережение заключается в том, что, поскольку основная версия таблицы все еще содержит 30-40 миллионов строк... ВСТАВКА и последующая репликация заканчивают тем, что на некоторое время блокируют ваше ведомое устройство (дублируя проблему выше), но это гораздо более короткая задержка (в итоге это заняло около 20 минут) из-за того, что mysql не нужно сканировать в базе данных строки для удаления.

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

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