MaxScale GTID 복제 중단 트러블슈팅 (feat. 내가 해결하려 했지만...)
시스템 구성
VIP 192.168.0.10
- 가상 IP, Active/Standby 전환 시 자동으로 Active DB를 가리킴
Master DB 192.168.0.11
- 쓰기 전담
Slave DB 192.168.0.12
- 읽기 전담 (복제 대상)
MaxScale의 readwritesplit 설정으로 Write는 Master, Read는 Slave로 자동 분리되는 구조다.
문제 발생
인지 시점
- 2026-03-26 백오피스 데이터 조회 중 이상 현상 발견
증상
증상 1. IDE에서 INSERT 후 백오피스에 데이터 미반영
1
2
IDE 툴에서 DBM(192.168.0.10)으로 직접 INSERT
→ 백오피스 화면에서 해당 데이터 조회 불가
증상 2. 백오피스에서 INSERT 후 화면에 미표시
1
2
3
백오피스에서 데이터 INSERT
→ DB 직접 조회 시엔 데이터 존재
→ 백오피스 화면에서는 데이터 미표시
원인 분석
MaxScale 로그 확인
1
tail -n 100 /var/log/maxscale/maxscale.log
로그에서 결정적인 내용 발견:
1
2
3
4
5
6
7
8
9
10
11
12
13
# 3월 12일 기록
2026-03-12 11:18:57 notice :
Server changed state: server2[192.168.0.12:3306]: lost_slave.
[Slave, Running] -> [Running]
SQL Running: No
Error: An attempt was made to binlog GTID 0-10-1000001
which would create an out-of-order sequence number
with existing GTID 0-11-1000000,
and gtid strict mode is enabled
# 오늘 기록
2026-03-26 16:46:52 notice : Updated 'passive' from 'false' to 'true'
2026-03-26 16:47:00 notice : Updated 'passive' from 'true' to 'false'
GTID란?
GTID(Global Transaction ID)는 DB에서 발생하는 모든 트랜잭션에 부여되는 전역 고유 식별자다.
1 2 형식: 도메인ID - ServerID - SequenceNumber 예시: 0 - 11 - 1000000
0→ 도메인 ID11→ 발생 서버 ID1000000→ 트랜잭션 순번
트랜잭션이 COMMIT 되는 순간 생성되며, Slave는 이 번호를 기반으로 어디까지 복제했는지 추적한다.
1
2
3
4
정상 복제 흐름:
Master COMMIT → GTID 발급 → Binary Log 기록
→ Slave IO Thread가 감지 → Relay Log로 복사
→ Slave SQL Thread가 순서대로 실행 → 데이터 반영
왜 충돌이 발생했나
1
2
3
4
5
정상: Master(server_id=11) 에서만 GTID 발급
0-11-1000000
실제: Slave(server_id=10) 에도 GTID가 생성됨
0-10-1000001 ← Slave에 직접 쓰기 발생 증거
MaxScale이 불안정한 상태(passive 전환)에서 쓰기 쿼리가 Slave로 라우팅된 것으로 추정된다.
gtid_strict_mode = ON 상태에서 순서가 어긋난 GTID는 데이터 정합성 보호를 위해 복제 자체를 거부한다.
결과적으로 3월 12일부터 Slave 복제가 중단된 채 운영 중이었다.
증상과 연결
IDE INSERT → 백오피스 미반영
- MaxScale이 IDE 세션을 Slave로 라우팅 (서로 다른 DB)
백오피스 INSERT → 화면 미표시
- Write는 Master 저장, Read는 복제 멈춘 Slave 조회
해결 방법 (내가 파악한 것)
즉시 조치
1
2
3
# Slave를 MaxScale 서비스에서 격리
# Read 쿼리가 복제 멈춘 Slave로 가지 않도록 차단
maxctrl set server server2 maintenance
복제 재동기화 옵션
GTID 강제 스킵
- 충돌 GTID만 건너뜀
- 적합: 충돌 건수 적을 때
mysqldump
- Master 데이터 전체 재주입
- 적합: DB 용량 작을 때
mariabackup
- 무중단 백업 후 재동기화
- 적합: 운영 환경 권장
1 2 3 4 5
-- GTID 강제 스킵 예시 (Slave에서 실행) STOP SLAVE; SET GLOBAL gtid_slave_pos = '0-11-1000000'; START SLAVE; SHOW SLAVE STATUS\G
해결하려 했지만…
원인도 파악했고, 해결 방법도 정리했다. maxctrl 명령어로 Slave 격리 후 복제 재동기화까지 진행할 수 있는 상황이었다.
근데 부장님이 막았다.
“너는 DBA가 아니잖아” “전문가도 아닌데 왜 건드려” “유지보수 업체 있는데 걔네한테 맡겨”
틀린 말은 아니다. 운영 DB 작업은 실수 한 번이 서비스 전체 장애로 이어질 수 있다. 부장님 입장에선 리스크 관리 차원에서 당연한 판단이다.
근데 솔직히 답답했다. MaxScale 로그도 직접 분석했고, GTID 충돌 원인도 특정했고, 해결 방법도 3가지나 파악해놨다. 우리 시스템 구조를 가장 잘 아는 사람이 나인데, 유지보수 업체가 와도 결국 내가 정리한 분석 내용 기반으로 작업하게 될 텐데.
결국 내가 한 건 분석 내용을 문서로 정리해서 유지보수 업체에 전달하는 것이었다. 직접 손은 못 댔지만, 원인 특정과 해결 방향은 내가 잡았다.
마무리
MaxScale 로그는 평소에 확인하는 습관을 들여야 한다. 이번 건은 복제 중단이 2주나 방치됐다. Slave에 직접 쓰기가 들어가면 GTID가 꼬이고, gtid_strict_mode가 켜져 있으면 데이터 정합성을 지키는 대신 복제를 아예 멈춰버린다.
그리고 하나 더 느낀 건, 기술적으로 할 수 있다는 것과 조직에서 해도 되는 건 별개라는 거다. 결국 문서화를 잘 해두는 게 중요하다.