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

Last Updated on 3월 17, 2021 by 태랑(정현호)


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 ….

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



1. 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



2. 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 에 대해서 처리를 진행하면 됩니다.

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




3. MSR의 Channel 사용시


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

3-1) 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 형태로 체크하면서 반복해서 진행 하는 것도 고려 할 수 있습니다.


3-2) 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





4. slave_skip_errors

slave_skip_errors 는 구성이나 데이터나 흐름 등의 이류로 자주 발생되는 에러가 있을 경우 slave 해당 에러만 skip 하여 replication 의 중단을 방지 할 수 있습니다.
비번하게 발생하고 구성이나 여러 이유로 skip 해야할 경우 my.cnf 에서 slave_skip_errors 를 설정하여 사용할 수 있습니다.

[mysqld]
slave_skip_errors=1032

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




관련된 다른 글

답글 남기기