[MySQL & MariaDB - Replication 복제 에러 error_code : 1236]

 배경

최근 Replication 구조에서 Primary DB가 갑작스레 서버가 죽으며, DB가 내려갔다.

이후 Slave DB에서 replication이 에라 발생과 함께 정상적으로 동작하지 않았다.

 

 

 발생 에러

  Slave status
MariaDB [(none)]> show slave status\G;
*************************** 1. row ***************************
                Slave_IO_State:
                   Master_Host: 192.168.152.128
                   Master_User: repl
                   Master_Port: 3306
                 Connect_Retry: 10
               Master_Log_File: mysql.000001
           Read_Master_Log_Pos: 568519
                Relay_Log_File: mysql-relay-bin.000002
                 Relay_Log_Pos: 568746
         Relay_Master_Log_File: mysql.000001
              Slave_IO_Running: No
             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: 568519
               Relay_Log_Space: 569055
               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
Master_SSL_Verify_Server_Cert: No
                 Last_IO_Errno: 1236
                 Last_IO_Error: Got fatal error 1236 from master when reading data from binary log: 'Client requested master to start replication from impossible position; the first event 'mysql.000001' at 568519, the last event read from 'mysql.000001' at 4, the last byte read from 'mysql.000001' at 4.'
                Last_SQL_Errno: 0
                Last_SQL_Error:
   Replicate_Ignore_Server_Ids:
              Master_Server_Id: 1
                Master_SSL_Crl:
            Master_SSL_Crlpath:
                    Using_Gtid: No
                   Gtid_IO_Pos:
       Replicate_Do_Domain_Ids:
   Replicate_Ignore_Domain_Ids:
                 Parallel_Mode: conservative
                     SQL_Delay: 0
           SQL_Remaining_Delay: NULL
       Slave_SQL_Running_State: Slave has read all relay log; waiting for the slave I/O thread to update it
              Slave_DDL_Groups: 1
Slave_Non_Transactional_Groups: 0
    Slave_Transactional_Groups: 3290
1 row in set (0.000 sec)

 

Slave에서 읽은 binlog의 pos값 568519이 Master에 저장된 동일한 binlog파일의 last pos값 568149보다 높은현상이 발생했다..

 

 

 발생 원인

에러 메시지와 동일하게 Slave에서는 Master의 다음 binlog 파일 pos값을 찾지 못해 에러가 발생.

 

이는 sync_binlog 파라미터가 0으로 설정되면 trx commit시에 바이너리 로그는 disk로 sync되지 않습니다.

따라서 Primary crash시점에 unflushed상태의 바이너리 로그 데이터는 사라지게 됩니다.

binary log가 linux 서버의 cached IO를 하기 때문에 unflushed 상태의 데이터를 Slave에서는 읽을수 있습니다.

 

즉 Master의 memory 상에서 page cache형태로 flush되지 않는 상태로 서비스 되기 때문에 Slave 서버에서 동기화 된

pos값이 Master 서버에 동일 binlog 파일의 last pos값보다 높은 현상 발생한 것 입니다.

 

■ Sync_binlog 

sync_binlog파라미터

 

MySQL 서버가 바이너리 로그를 디스크에 동기화하는 빈도를 제어합니다.

  • sync_binlog=0: MySQL 서버에 의한 바이너리 로그의 디스크 동기화를 비활성화합니다. 대신, MySQL 서버는 다른 파일과 마찬가지로 때때로 운영 체제를 사용하여 바이너리 로그를 디스크에 플러시합니다. 이 설정은 최상의 성능을 제공하지만 정전이나 운영 체제 충돌이 발생하는 경우 서버가 바이너리 로그에 동기화되지 않은 트랜잭션을 커밋했을 수 있습니다.
  • sync_binlog=1: 트랜잭션이 커밋되기 전에 바이너리 로그를 디스크에 동기화할 수 있습니다. 이는 가장 안전한 설정이지만 디스크 쓰기 횟수가 늘어나 성능에 부정적인 영향을 미칠 수 있습니다. 정전이나 운영 체제 충돌이 발생하는 경우 바이너리 로그에서 누락된 트랜잭션은 준비된 상태에만 있습니다. 이를 통해 자동 복구 루틴이 트랜잭션을 롤백할 수 있으므로 바이너리 로그에서 트랜잭션이 손실되지 않는 것이 보장됩니다.
  • sync_binlog=N, 여기서 는 N0 또는 1 이외의 값: 바이너리 N로그 커밋 그룹이 수집된 후 바이너리 로그가 디스크에 동기화됩니다. 정전이나 운영 체제 충돌이 발생하는 경우 서버에서 바이너리 로그에 기록되지 않은 트랜잭션을 커밋했을 수 있습니다. 이 설정은 디스크 쓰기 횟수 증가로 인해 성능에 부정적인 영향을 미칠 수 있습니다. 값이 높을수록 성능이 향상되지만 데이터 손실 위험이 높아집니다.

 

 

 

 해결 방법

Master-Slave간 데이터 정합성을 위해 Slave를 재구성하는게 일반적입니다.

하지만 아래와 같이 docs에서는 해결방법을 알려주나 이는 데이터 정합성을 보장하지 못하는 해결방법이므로 반드시 정합성 검사를 진행해보는 것을 추천드립니다.(sync_binlog값이 0인 경우)

 

https://mariadb.com/resources/blog/client-requested-master-to-start-replication-from-impossible-position/

 

Client requested master to start replication from impossible position | MariaDB

If you run a replicated MySQL setup and have a master failure, you may see the following error in your error log. At this point your slave will not be replicating and you will need to recover from the…

mariadb.com

 

ㅁ  Replication 재정의

- 현재 읽고 있는 Binlog파일의 다음 파일로 지정. 즉, 현재 mysql.00001을 읽고 있으므로 mysql.00002로 지정해줍니다. 또한 새로운 binlog파일의 첫 시작 position번호는 4로 시작합니다. 따라서 change master시 0또는 4로 지정하여 복제를 재시작합니다.

MariaDB [(none)]> stop slave;
Query OK, 0 rows affected (0.002 sec)


MariaDB [(none)]> CHANGE MASTER TO MASTER_HOST='192.168.152.128', MASTER_USER='repl',MASTER_PASSWORD='repl',MASTER_PORT=3306,MASTER_LOG_FILE='mysql.000002', MASTER_LOG_POS=0,MASTER_CONNECT_RETRY=10;
Query OK, 0 rows affected (0.005 sec)


MariaDB [(none)]> start slave;
Query OK, 0 rows affected (0.001 sec)


MariaDB [(none)]> show slave status\G;
*************************** 1. row ***************************
                Slave_IO_State: Waiting for master to send event
                   Master_Host: 192.168.152.128
                   Master_User: repl
                   Master_Port: 3306
                 Connect_Retry: 10
               Master_Log_File: mysql.000002
           Read_Master_Log_Pos: 338
                Relay_Log_File: mysql-relay-bin.000002
                 Relay_Log_Pos: 633
         Relay_Master_Log_File: mysql.000002
              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: 338
               Relay_Log_Space: 942
               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: 0
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
                Master_SSL_Crl:
            Master_SSL_Crlpath:
                    Using_Gtid: No
                   Gtid_IO_Pos:
       Replicate_Do_Domain_Ids:
   Replicate_Ignore_Domain_Ids:
                 Parallel_Mode: conservative
                     SQL_Delay: 0
           SQL_Remaining_Delay: NULL
       Slave_SQL_Running_State: Slave has read all relay log; waiting for the slave I/O thread to update it
              Slave_DDL_Groups: 1
Slave_Non_Transactional_Groups: 0
    Slave_Transactional_Groups: 3290
1 row in set (0.000 sec)

 

 

다음 글에서 sync_binlog 0 또는 1값에 따른 데이터 정합성 유지 테스트를 진행하겠습니다.