MySQL 복제 문제 발생시 Skip - Replication Error Skip

Share

Last Updated on 1월 20, 2024 by Jade(정현호)


MySQL 의 복제(Replication, 동기화) 를 사용하는 과정에서 여러 이유로 Slave 에서 복제가 중단될 수 있습니다. 문제 발생시 Slave(Replica) 노드에서 show slave status\G 를 하였을 때 아래와 같은 에러 메세지가 확인됩니다

에러 메세지는 다양하게 나타나며 아래는 예시입니다.


Last_SQL_Error: Error Duplicate entry 2 for key 1 on query. Default database: TESTDB. Query: INSERT INTO ....

발생된 에러 내역에 따라 조치 방안은 달라질 수 있으나 PK 키가 중복된 상태이거나 이미 테이블이 생성이 되었다는 에러나 이미 유저가 생성이 되어있다는 에러의 유형과 같이 skip(해당 트랜잭션을 drop) 이 필요하거나 해도 무방할 경우 skip 을 고려할 수 있습니다.
           

sql_slave_skip_counter 사용

sql_slave_skip_counter 를 사용하여 에러가 난 만큼을 skip 을 할 수 있으며 이 방법은 gtid 를 사용하지 않는 master binlog 와 pos 정보를 통하여 replication 하는 환경에서 사용하면 됩니다.

1개의 에러만큼 skip을 하려면 아래의 진행 순서대로 하면 됩니다.

mysql> stop slave;
mysql> set global sql_slave_skip_counter=1;

mysql> start slave;
mysql> show slave status\G


skip 하였으나 다시 replication 에러가 발생할 경우 위의 과정을 재차 반복합니다.
            

GTID_NEXT 사용

gtid 즉 Global Transaction IDentifier 를 사용하여 Replication 을 사용하는 환경에서는 gtid_next 를 통해서 skip 을 진행할 수 있습니다.

Last_SQL_Error: Error 'Operation CREATE USER failed for 'test'@'%'' on query. Default database: ''

Retrieved_Gtid_Set: 1f3b100f-8275-11eb-b444-08002761d7ed:1-1405
Executed_Gtid_Set: 1f3b100f-8275-11eb-b444-08002761d7ed:1-1402,


위와 같이 에러가 발생시 1402 까지는 진행된 상태이고 1403 에서 에러가 발생된 상태임으로 1403 에 대해서 처리를 진행하면 됩니다.

또는 performance_schema.replication_applier_status_by_worker 를 조회하면 아래와 같이 에러 내역을 더 자세히 확인할 수 있습니다.

mysql> selct * 
from performance_schema.replication_applier_status_by_worker\G

******************** 1. row *********************
CHANNEL_NAME: REPL_CH1
WORKER_ID: 1
THREAD_ID: NULL
SERVICE_STATE: OFF
LAST_SEEN_TRANSACTION : 1f3b100f-8275-11eb-b444-08002761d7ed:1-1403 
LAST_ERROR_NUMBER: 1133
LAST_ERROR_MESSAGE: Worker 1 failed executing .... 1f3b100f-8275-11eb-b444-08002761d7ed:1-1403
LAST_ERROR_TIMESTAMP: 2021-03-12 ...

[참고] 5.7 버전 기준의 정보이며, 8.0 버전에서는 더 많은 컬럼 정보가 있습니다.

위의 정보에서도 1403 를 처리하던 중 문제가 발생되었음을 알 수 있습니다.



SET GTID_NEXT 입력 시 아래와 같이 -(대시) 앞에는 제외하고 입력하면 됩니다.

mysql> SET GTID_NEXT="1f3b100f-8275-11eb-b444-08002761d7ed:1403";


그리고 문제가 된 트랜잭션을 skip 할 수 있도록 임의의 트랜잭션을 생성하고 나서 다시 replication 을 시작합니다.

mysql> begin;
mysql> commit;

mysql> set gtid_next='AUTOMATIC';
mysql> start slave;


replication 상태를 조회해보면 정상적으로 skip이 되는 것을 확인할 수 있습니다.

mysql> show slave status\g

             

MSR의 Channel 사용시

Multi Source Replication(MSR) 으로 되어 있을 경우 아래와 채널 별 중지 및 시작 등으로 skip 을 수행할 수 있습니다.
   

binlog,Pos 사용 환경

mysql> stop slave for channel 'ch_master1';
mysql> set global sql_slave_skip_counter=1;

mysql> start slave for channel 'ch_master1';
mysql> show slave status for channel 'ch_master1'\G


# 복제 상태 정상으로 변경됨
# Slave_SQL_Running_State: Slave has read all relay log; waiting for more updates


[참고] error 가 skip 되었다면 sql_slave_skip_count 는 0 으로 됩니다
그래서 가령 여러 채널에서 에러가 발생되어 채널별로 skip을 진행한다면 "1번 채널 stop -> skip=1 -> 1번 채널 start , 그리고 2번 채널 stop -> skip=1 -> 2번 채널 start" 와 같이 skip 구문을 여러번 써주거나 skip을 처음 부터 숫자를 높이거나 하는 방법을 고려할 수 있습니다.
1건의 skip 마다 확인 후 진행하고자 한다면 skip=1 -> 시작 한다음 status 로 확인 후 여전히 skip 할 내역이 남아 있다면 stop-> skip=1 -> start 형태로 체크하면서 반복해서 진행하는 것도 고려할 수 있습니다.
            

GTID 사용 환경

gtid 즉 Global Transaction IDentifier 를 사용하여 Replication 을 사용하는 환경에서는 gtid_next 를 통해서 skip 을 진행할 수 있습니다.

포스팅에서는 1418 트랜잭션을 skip 해야 하는 상황입니다.
mysql> stop slave for channel 'ch_master1';

# 현재 Replication 상황
Last_SQL_Error: Error 'Unknown database 'tdb'' on query.
Default database: 'testdb1'. 
Query: 'create table tdb.tb_error1(no int)'
<중략>
Retrieved_Gtid_Set: 1f3b100f-8275-11eb-b444-08002761d7ed:1412-1418
Executed_Gtid_Set: 1f3b100f-8275-11eb-b444-08002761d7ed:1-1417

# 1418 트랜잭션을 skip 해야 하는 상황


절차는 아래와 같이 수행하면 됩니다.

mysql> SET GTID_NEXT="1f3b100f-8275-11eb-b444-08002761d7ed:1418";


# 그리고 문제가 된 트랜잭션을 skip 할 수 있도록 
# 임의의 트랜잭션을 생성 하고 나서 다시 replication 을 시작합니다.

mysql> begin;
mysql> commit;   
mysql> set gtid_next='AUTOMATIC';
mysql> start slave for channel 'ch_master1';

mysql> show slave status for channel 'ch_master1'\G

            

slave_skip_errors

slave_skip_errors 는 구성이나 데이터나 흐름 등의 이류로 자주 발생되는 에러가 있을 경우 slave 해당 에러만 skip 하여 replication 의 중단을 방지할 수 있습니다.

에러가 빈번하게 발생하고 구성이나 여러 이유로 skip 해야 할 경우 my.cnf 에서 slave_skip_errors 를 설정하여 사용할 수 있습니다.

[mysqld]
slave_skip_errors=1032


,(콤마) 를 사용하여 여러 개의 에러 코드를 설정할 수 있습니다.



관련된 다른 글

 

 

 

 

 

 

 

2
0
글에 대한 당신의 생각을 기다립니다. 댓글 의견 주세요!x