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

Проблемы репликации MySQL после отключения электроэнергии

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

Это в журналах одного из ведомых устройств:

100118 10:05:56 [Note] Slave I/O thread: connected to master 'repl@db1:3306',  replication started in log 'bin-log.004712' at position 724207814
100118 10:05:56 [ERROR] Error reading packet from server: Client requested master to start replication from impossible position ( server_errno=1236)
100118 10:05:56 [ERROR] Got fatal error 1236: 'Client requested master to start replication from impossible position' from master when reading data from binary log
100118 10:05:56 [Note] Slave I/O thread exiting, read up to log 'bin-log.004712', position 724207814

И консоль показывает чуть подробнее:

mysql> show slave status \G;
*************************** 1. row ***************************
             Slave_IO_State:
                Master_Host: db1
                Master_User: repl
                Master_Port: 3306
              Connect_Retry: 10
            Master_Log_File: bin-log.004712
        Read_Master_Log_Pos: 724207814
             Relay_Log_File: mysqld-relay-bin.000105
              Relay_Log_Pos: 98
      Relay_Master_Log_File: bin-log.004712
           Slave_IO_Running: No
          Slave_SQL_Running: Yes
            Replicate_Do_DB: mmplive1,mmpjcr,fui
        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: 724207814
            Relay_Log_Space: 98
            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: NULL
1 row in set (0.00 sec)

ERROR:
No query specified

Глядя на журналы бункера на мастере, мы имеем:

-rw-rw---- 1 mysql mysql  724200412 Jan 18 09:22 bin-log.004712
-rw-rw---- 1 mysql mysql       1904 Jan 18 09:27 bin-log.index
-rw-rw---- 1 mysql mysql    5046830 Jan 18 11:22 slow-log
-rw-rw---- 1 mysql mysql  198249613 Jan 18 11:24 bin-log.004713
  1. Статус Slave показывает, что Exec_Master_Log_Pos и ​​Read_Master_Log_Pos оба равны 724207814, для двоичного журнала bin-log.004712. Насколько я понимаю, это значение представляет собой позицию байта в двоичном файле журнала.
  2. Размер этого файла bin-log.004712 составляет всего 724200412 байтов, поэтому ведомые устройства думают, что они выполнили на 7402 байта больше работы, чем было фактически сохранено в файле (который находится на ext3 fs, RAID-10, RHEL5). Отсюда сообщение об ошибке о невозможности положения журнала и т. Д.

Как лучше всего починить рабов?

Варианты, которые я рассматриваю:

  1. Установка каждого ведомого устройства на позицию 0 в следующем файле bin-log (bin-log.004713) и отпустить их, но я не уверен, насколько это безопасно или сколько данных может быть потеряно.
  2. Должен ли я вместо этого делать полное резервное копирование и восстановление (с предполагаемым временем простоя из-за блокировок таблиц в таблицах InnoDB)? По возможности я бы хотел этого избежать.

ОБНОВИТЬ:

Я пропустил еще один вариант: немного вернуть каждую позицию выполнения ведомого, чтобы он попытался воспроизвести команды, которые он уже обработал из bin-log.004712.

Я выбрал первый вариант.

Это работало до того момента, когда ведомое устройство начало пытаться делать вставки, конфликтующие с первичными ключами. Подчиненное устройство выполнило больше работы, чем сохранялось в главном журнале бункера, как упоминалось ранее. Один аспект, который я не ожидал, заключался в том, что подчиненное устройство содержало данные, которых не было в главном устройстве; то есть ведомое устройство сохранило некоторые транзакции до отключения электроэнергии, которое ведущее устройство НЕ ИМЕЛ настаивал.

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

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

  • Поменял лог файл и положение на раб.

    CHANGE MASTER MASTER_LOG_FILE='bin-log.004713', MASTER_LOG_POS=0; -- on serverB
    
  • Перезапущена репликация подчиненного устройства на пассивном главном устройстве (serverB) до тех пор, пока не произойдет сбой с нарушением ограничений первичного ключа, как и в случае с другими подчиненными устройствами.

     START SLAVE; -- on serverB
    
  • Остановлена ​​репликация ведомого устройства от пассивного ведущего (serverB) к активному ведущему (serverA).

    STOP SLAVE; -- on serverA
    
  • УДАЛИТЕ строки на подчиненном сервере (serverB), которых не было в главном устройстве на serverA.

    DELETE FROM SOME_TABLE WHERE ID IN (???,????); -- on serverB
    SHOW MASTER STATUS\G; -- get the new master log position on serverB
    
  • Переместите позицию exec активного ведущего (serverA) ведомого, чтобы пропустить эти удаления с пассивного ведущего (serverB).

    CHANGE MASTER TO MASTER_LOG_POS=???; --on serverA; use the value just obtained from serverB
    
  • Перезапустите репликацию как на активном мастере (serverA), так и на пассивном мастере.

    START SLAVE; -- on both machines. serverA does nothing and serverB starts catching up.
    

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