Назад | Перейти на главную страницу

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 вообще продвинулась, пока я наблюдал за ними сегодня утром.

Заглянув в журналы на главном сервере, это утверждение находится по адресу 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

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

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

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

Спасибо.


Для справки вот 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)

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

После переноса данных я выполнил оператор 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).

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

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;

Поскольку DELETE был выполнен на Мастере, INSERT здесь вставил только те записи, которые я хотел сохранить (удаленные исчезли). И, поскольку репликация на основе строк вставляет каждую строку отдельно вместо выполнения того же оператора INSERT INTO ... SELECT, таблица Slave была заполнена только желаемыми данными. Затем последующий оператор DROP TABLE удаляет таблицу на ведомом устройстве, не обращаясь к каждой строке отдельно.

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

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