MySQL Position 설정(SBR의 경우 무엇으로 맞출까?)
슬레이브 비정상 종료, 재구동 이후 복제를 위한 positioning 중, auto_increment 값이 맞지 않는 현상 분석
MySQL 롤백으로 인한 M-S 비일치를 발생시킴
상기의 모델은 마스터-리플간 불일치 발생으로 인한 건으로, 리플리케이션이 늦은 상태가 되나,
원래 테스트하려고 했던 현상은 binlog상태 <> 실제 DB서버에 커밋된 상태(DB서버에 커밋된 상태가 빈로그 상태보다 더 앞선 상태로, 릴레이로그의 커밋된 부분이 커밋 안된 부분으로 나타나는 현상)이나,
해당 현상은 재현하지 못한 관계로 수동으로 상황을 재현하여 테스트.
시나리오 작성
현재 포지션 값 저장
50000건 인서트(슬레이브도 쫓아가도록)
포지션값 1. 의 포지션값으로 변경(50000건 차이 발생했으나, 실제론 데이터 입력된 상태)
어느 값으로 변경했을 때 insert_id가 변경되는지 확인.
-- 현재 슬레이브 상태와 마스터 상태
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 | mysql> show master status; +------------------+----------+--------------+------------------+ | File | Position | Binlog_Do_DB | Binlog_Ignore_DB | +------------------+----------+--------------+------------------+ | mysql-bin.000128 | 4186214 | | | +------------------+----------+--------------+------------------+ 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: 10.30.101.158 Master_User: kimgn_test_repl Master_Port: 3306 Connect_Retry: 60 Master_Log_File: mysql-bin.000128 Read_Master_Log_Pos: 4186214 Relay_Log_File: kimgn-test-relay-bin.000230 Relay_Log_Pos: 4186360 Relay_Master_Log_File: mysql-bin.000128 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: 4186214 Relay_Log_Space: 4186564 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 1 row in set (0.00 sec) | cs |
-- 50,000건 데이터 입력후, 이전 포지션 값으로 변경 후 테스트 시작.
-- 해당 에러 해결을 위해 현재 문제가 된 값을 찾아 binlog open(의도적으로 수행 전으로 돌렸으므로 131번 오픈)
root@kimgn-splunk-test /data/mysql_1/data
$ /mysql/bin/mysqlbinlog mysql-bin.000131 > ./test.sql
에러가 난 값은 1200001 이나, 현재 들어간 값까지 문제가 없다는 가정 하에 슬레이브의 PK 맥스값 검색
mysql> select max(id) fROM kimgn_test.kimgn_test;
+---------+
| max(id) |
+---------+
| 1250000 |
+---------+
1250000 에 해당하는 positon 탐색(파일의 위치 등은 시간을 통해 유추하나, 여기서는 131번으로 확인(변경 테스트 포지션은 볼드처리)
# at 5477845
#180103 16:14:58 server id 1 end_log_pos 5477872 Xid = 4247603
COMMIT/*!*/;
# at 5477872
#180103 16:14:58 server id 1 end_log_pos 5477954 Query thread_id=257606 exec_time=0 error_code=0
SET TIMESTAMP=1514963698/*!*/;
BEGIN
/*!*/;
# at 5477954
#180103 16:14:58 server id 1 end_log_pos 5477982 Intvar
SET INSERT_ID=1250000/*!*/;
# at 5477982
#180103 16:14:58 server id 1 end_log_pos 5478017 Rand
SET @@RAND_SEED1=22686107, @@RAND_SEED2=1027190506/*!*/;
# at 5478017
#180103 16:14:58 server id 1 end_log_pos 5478172 Query thread_id=257606 exec_time=0 error_code=0
SET TIMESTAMP=1514963698/*!*/;
INSERT INTO kimgn_test (contents,date_val) VALUES ( CEILING(RAND()*100),now())
/*!*/;
# at 5478172
#180103 16:14:58 server id 1 end_log_pos 5478199 Xid = 4247604
COMMIT/*!*/;
시나리오 : 현재 1250000 번까지 들어가 있으므로 1250000을 인서트 시도 후 에러가 나면 skip 후 정상 인서트 확인.(현재 데이터는 1300000까지 들어가 있음)
케이스 1 : INSERT_ID를 지정하는 포지션인 5477954 로 지정
케이스 2 : INSERT_ID를 지정하는 포지션 중 end_pos로 지정되어 있는 5477982 로 지정
케이스 3 : BEGIN과 TIMESTAMP를 지정하는 5477872 로 지정
케이스 1 시나리오 결과
의도한 대로 원하는 곳에서 한번 더 STOP 발생
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 | mysql> show slave status\G *************************** 1. row *************************** Slave_IO_State: Waiting for master to send event Master_Host: 10.30.101.158 Master_User: kimgn_test_repl Master_Port: 3306 Connect_Retry: 60 Master_Log_File: mysql-bin.000134 Read_Master_Log_Pos: 6770842 Relay_Log_File: kimgn-test-relay-bin.000002 Relay_Log_Pos: 253 Relay_Master_Log_File: mysql-bin.000131 Slave_IO_Running: Yes Slave_SQL_Running: No Replicate_Do_DB: Replicate_Ignore_DB: Replicate_Do_Table: Replicate_Ignore_Table: Replicate_Wild_Do_Table: Replicate_Wild_Ignore_Table: Last_Errno: 1062 Last_Error: Error 'Duplicate entry '1250000' for key 'PRIMARY'' on query. Default database: 'kimgn_test'. Query: 'INSERT INTO kimgn_test (contents,date_val) VALUES ( CEILING(RAND()*100),now())' Skip_Counter: 0 Exec_Master_Log_Pos: 5477954 Relay_Log_Space: 32753048 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: 0 Last_IO_Error: Last_SQL_Errno: 1062 Last_SQL_Error: Error 'Duplicate entry '1250000' for key 'PRIMARY'' on query. Default database: 'kimgn_test'. Query: 'INSERT INTO kimgn_test (contents,date_val) VALUES ( CEILING(RAND()*100),now())' Replicate_Ignore_Server_Ids: Master_Server_Id: 1 1 row in set (0.00 sec) | cs |
sql 스레드 스킵 후 데이터 확인 결과 원하는 대로 데이터 입력됨을 확인할 수 있었음.
케이스 2 시나리오 결과
의도한 대로 원하는 곳에서 한번 더 STOP 발생
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 | mysql> show slave status\G *************************** 1. row *************************** Slave_IO_State: Waiting for master to send event Master_Host: 10.30.101.158 Master_User: kimgn_test_repl Master_Port: 3306 Connect_Retry: 60 Master_Log_File: mysql-bin.000134 Read_Master_Log_Pos: 6770842 Relay_Log_File: kimgn-test-relay-bin.000002 Relay_Log_Pos: 253 Relay_Master_Log_File: mysql-bin.000131 Slave_IO_Running: Yes Slave_SQL_Running: No Replicate_Do_DB: Replicate_Ignore_DB: Replicate_Do_Table: Replicate_Ignore_Table: Replicate_Wild_Do_Table: Replicate_Wild_Ignore_Table: Last_Errno: 1062 Last_Error: Error 'Duplicate entry '1250000' for key 'PRIMARY'' on query. Default database: 'kimgn_test'. Query: 'INSERT INTO kimgn_test (contents,date_val) VALUES ( CEILING(RAND()*100),now())' Skip_Counter: 0 Exec_Master_Log_Pos: 5477954 Relay_Log_Space: 32753048 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: 0 Last_IO_Error: Last_SQL_Errno: 1062 Last_SQL_Error: Error 'Duplicate entry '1250000' for key 'PRIMARY'' on query. Default database: 'kimgn_test'. Query: 'INSERT INTO kimgn_test (contents,date_val) VALUES ( CEILING(RAND()*100),now())' Replicate_Ignore_Server_Ids: Master_Server_Id: 1 1 row in set (0.00 sec) | cs |
sql 스레드 스킵(케이스 1의 경우 1회였으나, 케이스 2의 경우 2회) 후 데이터 확인 결과 skip 대상이었던 kimgn_test 테이블의 데이터가 1건 오입력됨을 확인할 수 있었음.
원인 분석 : 데이터 확인 결과, 최초 스킵한 1250001번의 데이터가 1250000번 의 데이터와 데이터가 일치함.
즉, 앞에서 skip을 의도했던 INSERT구문이 수행 완료되었음을 확인할 수 있었음.
추가적으로 앞에서 SKIP하려 했던 auto_increment값이 에러가 나도, 그 이후 값은 정상적으로 입력되는 것 확인.
--1. 마스터 서버의 데이터 : 1,300,000건
mysql> select * FROM kimgn_test order by id desc LIMIT 10;
+---------+----------+---------------------+
| id | contents | date_val |
+---------+----------+---------------------+
| 1300000 | 2 | 2018-01-03 18:02:29 |
| 1299999 | 32 | 2018-01-03 18:02:29 |
| 1299998 | 67 | 2018-01-03 18:02:29 |
| 1299997 | 72 | 2018-01-03 18:02:29 |
| 1299996 | 87 | 2018-01-03 18:02:29 |
| 1299995 | 65 | 2018-01-03 18:02:29 |
| 1299994 | 71 | 2018-01-03 18:02:29 |
| 1299993 | 54 | 2018-01-03 18:02:29 |
| 1299992 | 50 | 2018-01-03 18:02:29 |
| 1299991 | 66 | 2018-01-03 18:02:29 |
+---------+----------+---------------------+
10 rows in set (0.01 sec)
mysql> select * FROM kimgn_test order by id desc LIMIT 49995,10;
+---------+----------+---------------------+
| id | contents | date_val |
+---------+----------+---------------------+
| 1250005 | 7 | 2018-01-03 18:02:10 |
| 1250004 | 70 | 2018-01-03 18:02:10 |
| 1250003 | 2 | 2018-01-03 18:02:10 |
| 1250002 | 51 | 2018-01-03 18:02:10 |
| 1250001 | 40 | 2018-01-03 18:02:10 |
| 1250000 | 3 | 2018-01-03 16:14:58 |
| 1249999 | 37 | 2018-01-03 16:14:58 |
| 1249998 | 88 | 2018-01-03 16:14:58 |
| 1249997 | 14 | 2018-01-03 16:14:58 |
| 1249996 | 31 | 2018-01-03 16:14:58 |
+---------+----------+---------------------+
10 rows in set (0.02 sec)
--2. 슬레이브 서버의 데이터: 1,300,000건
mysql> select * FROM kimgn_test order by id desc LIMIT 10;
+---------+----------+---------------------+
| id | contents | date_val |
+---------+----------+---------------------+
| 1300000 | 2 | 2018-01-03 18:02:29 |
| 1299999 | 32 | 2018-01-03 18:02:29 |
| 1299998 | 67 | 2018-01-03 18:02:29 |
| 1299997 | 72 | 2018-01-03 18:02:29 |
| 1299996 | 87 | 2018-01-03 18:02:29 |
| 1299995 | 65 | 2018-01-03 18:02:29 |
| 1299994 | 71 | 2018-01-03 18:02:29 |
| 1299993 | 54 | 2018-01-03 18:02:29 |
| 1299992 | 50 | 2018-01-03 18:02:29 |
| 1299991 | 66 | 2018-01-03 18:02:29 |
+---------+----------+---------------------+
10 rows in set (0.00 sec)
mysql> select * FROM kimgn_test order by id desc LIMIT 49995,10;
+---------+----------+---------------------+
| id | contents | date_val |
+---------+----------+---------------------+
| 1250005 | 7 | 2018-01-03 18:02:10 |
| 1250004 | 70 | 2018-01-03 18:02:10 |
| 1250003 | 2 | 2018-01-03 18:02:10 |
| 1250002 | 51 | 2018-01-03 18:02:10 |
| 1250001 | 3 | 2018-01-03 16:14:58 |
| 1250000 | 3 | 2018-01-03 16:14:58 |
| 1249999 | 37 | 2018-01-03 16:14:58 |
| 1249998 | 88 | 2018-01-03 16:14:58 |
| 1249997 | 14 | 2018-01-03 16:14:58 |
| 1249996 | 31 | 2018-01-03 16:14:58 |
+---------+----------+---------------------+
10 rows in set (0.01 sec)
케이스 3 시나리오 결과
의도한 대로 원하는 곳에서 한번 더 STOP 발생
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 | mysql> show slave status\G *************************** 1. row *************************** Slave_IO_State: Waiting for master to send event Master_Host: 10.30.101.158 Master_User: kimgn_test_repl Master_Port: 3306 Connect_Retry: 60 Master_Log_File: mysql-bin.000134 Read_Master_Log_Pos: 6770842 Relay_Log_File: kimgn-test-relay-bin.000002 Relay_Log_Pos: 253 Relay_Master_Log_File: mysql-bin.000131 Slave_IO_Running: Yes Slave_SQL_Running: No Replicate_Do_DB: Replicate_Ignore_DB: Replicate_Do_Table: Replicate_Ignore_Table: Replicate_Wild_Do_Table: Replicate_Wild_Ignore_Table: Last_Errno: 1062 Last_Error: Error 'Duplicate entry '1250000' for key 'PRIMARY'' on query. Default database: 'kimgn_test'. Query: 'INSERT INTO kimgn_test (contents,date_val) VALUES ( CEILING(RAND()*100),now())' Skip_Counter: 0 Exec_Master_Log_Pos: 5477954 Relay_Log_Space: 32753048 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: 0 Last_IO_Error: Last_SQL_Errno: 1062 Last_SQL_Error: Error 'Duplicate entry '1250000' for key 'PRIMARY'' on query. Default database: 'kimgn_test'. Query: 'INSERT INTO kimgn_test (contents,date_val) VALUES ( CEILING(RAND()*100),now())' Replicate_Ignore_Server_Ids: Master_Server_Id: 1 1 row in set (0.00 sec) | cs |
sql 스레드 스킵 후 데이터 확인 결과 원하는 대로 데이터 입력됨을 확인할 수 있었음.
추가 테스트 사항, UPDATE시 결정 값이 고정적이지 않을 때 SBR에서 두번 실행되지 않을까?
상기의 케이스에서 , UPDATE하려는 칼럼의 값이 기존 값에서 계산하는 형식이라면, 해당 명령이 두번 수행되어 마스터와 슬레이브 노드의 데이터가 일치하지 않지 않을지 확인
테스트 시나리오
PK 데이터 입력
UPDATE 구문 수행(UPDATE test_temp SET info= info + 1 where id=1)\
PK 데이터 입력
슬레이브 포지션 1 이전의 상태로 복원
set global sql_slave_skip_counter=1; 문장을 이용해 sync 동기화
테스트 결과
상기와 같은 결과값이 일정하지 않은 쿼리 또한 반영하여 처리하는 것으로 보임. 해당 쿼리를 포함한 binlog 값을 변경하였음에도 불구하고 계속적으로 test_temp 테이블의 info 칼럼의 값이 일치하는 것을 확인할 수 있었음
결론
begin에 해당하는 at ... 번호를 찍는 것이 가장 좋을 것으로 보임
end_log_pos는 해당 명령을 수행하고 난 후의 포지션을 의미하기 때문에,
실제 포지션은 명령 이전에 존재하는 # at 포지션번호 임.
# at 5477872
#180103 16:14:58 server id 1 end_log_pos 5477954 Query thread_id=257606 exec_time=0 error_code=0
SET TIMESTAMP=1514963698/*!*/;
BEGIN