깨진 replica 복구: 1062 / 1032 행 충돌
MySQL복제명령어
-- 1) Failing worker, error and GTID
SELECT WORKER_ID, LAST_ERROR_NUMBER, LEFT(LAST_ERROR_MESSAGE, 250) AS last_error, APPLYING_TRANSACTION
FROM performance_schema.replication_applier_status_by_worker
WHERE LAST_ERROR_NUMBER <> 0;
-- 2) Shell: decode the row images of that transaction from the relay log
mysqlbinlog --base64-output=DECODE-ROWS -vv --include-gtids='af6bc361-c353-11f1-8f12-f69e63ad6c0e:11' /var/lib/mysql/db2-relay-bin.0* | grep '^###'
-- 3a) 1062 Duplicate entry: delete the extra row on the replica without binlogging
SET SESSION sql_log_bin = 0;
DELETE FROM shop.orders WHERE id = 20001;
-- 3b) 1032 Can't find record: insert the missing row from the WHERE (before image) values
INSERT INTO shop.orders (id, cust, amount, note, created) VALUES (6, 6, 9.00, 'n6', '2026-10-08 20:09:44');
SET SESSION sql_log_bin = 1;
-- 4) Start the applier and verify
START REPLICA SQL_THREAD;
SELECT SERVICE_STATE, LAST_ERROR_NUMBER FROM performance_schema.replication_applier_status_by_coordinator;하는 일
가장 흔한 두 가지 row 기반 복제 중단(1062 duplicate key, 1032 row not found)을 트랜잭션을 건너뛰지 않고 replica의 행을 source가 기대하는 상태로 맞춰 해결한다. 데이터 일관성이 유지된다.
사용 시점
Replica_SQL_Running = No이고 오류 1062 / 1032일 때. 빈 트랜잭션으로 GTID를 건너뛰는 대신 올바른 복구 방법으로.
주의
replica에서의 수정은 sql_log_bin=0으로 실행해야 한다. 그렇지 않으면 errant GTID가 생겨 페일오버 시 문제가 된다. super_read_only=ON이면 일시적으로 끄고 나중에 다시 켠다. before-image 값은 binlog_row_image=FULL을 전제로 한다. MINIMAL이면 PK만 기록되므로 나머지 행은 source에서 읽어야 한다. 한 테이블에 충돌이 하나 있으면 대개 더 있으므로 복구 후 pt-table-checksum으로 테이블을 source와 비교한다. relay log 경로: SELECT @@relay_log_basename;