ssuperjun 님의 블로그
[장애 이력 자동 작성 도구 14] MySQL 장애 연출 본문
장애 연출 계획
각 장애마다 연출 → 로그 확인 → 패턴 확정 → 코드 반영 사이클을 반복
싱글 구성 (ca801)
| 순서 | 장애 유형 | 연출 방법 |
| 1 | 재시작 (정상) | mysqladmin shutdown 후 재시작 — 기준선 확보 |
| 2 | OOM Kill | stress-ng 또는 INSERT 루프로 메모리 고갈, vm.overcommit_memory 조정 |
| 3 | Too Many Connections | max_connections=5 설정 후 다수 연결 |
| 4 | 디스크 Full | fallocate로 디스크 채우기 |
| 5 | Segfault | kill -SIGSEGV {mysqld_pid} |
복제 구성 (ca801 마스터 → cb801 레플리카)
| 순서 | 장애 유형 | 연출 방법 |
| 6 | 복제 연결 단절 (마스터 재시작) | ca801에서 mysqld 재시작 |
| 7 | 복제 연결 단절 (네트워크 단절) | iptables로 ca801↔cb801 포트 차단/해제 |
이후 더 추가된 사항
8. 마스터-레플리카 간 데이터 정합성 장애 유발: 레플리카에서 직접 데이터를 수정한 뒤 마스터에서 동일 row를 건드려 충돌 유발
9. 레플리카의 디스크 Full 장애 유발: 마스터의 데이터를 레플리카가 동기화하는 과정에서 레플리카의 디스크 용량을 부족하게 설정
1번 장애(MySQL 정상 종료)
1단계 - 현재 로그 끝 위치 확인:
wc -l /home1/irteam/mysql/log/mysql.err
2단계
# mysqld_safe로 직접 프로세스 종료
kill $(cat /home1/irteam/mysql/run/mysql.pid)
sleep 3
tail -10 /home1/irteam/mysql/log/mysql.err
3단계
재시작 후 로그 확인
nohup /home1/irteam/mysql/base/bin/mysqld_safe \
--defaults-file=/home1/irteam/mysql/my.cnf > /dev/null 2>&1 &
sleep 5 && tail -5 /home1/irteam/mysql/log/mysql.err
결과
MySQL 재시작 흐름 정리
06:01:07 [MY-013172] Received SHUTDOWN from user <via user signal>
└─ SIGTERM 수신, 정상 종료 시작
06:01:16 [MY-010910] Shutdown complete
└─ mysqld 프로세스 종료 완료
06:01:16 mysqld_safe mysqld from pid file ... ended
└─ mysqld_safe가 mysqld 종료를 감지하고 자신도 종료
(SIGTERM은 정상 종료 신호이므로 재시작 없이 종료)
── 약 4분 공백 (mysqld_safe가 없는 상태) ──
06:05:12 mysqld_safe Logging to '...mysql.err'
06:05:12 mysqld_safe Starting mysqld daemon with databases from ...
└─ 새 mysqld_safe 프로세스 시작 (nohup 명령 실행)
06:05:12 [MY-010116] mysqld starting as process 2161032
└─ mysqld 프로세스 생성
06:05:12 [MY-013576] InnoDB initialization has started
06:05:13 [MY-013577] InnoDB initialization has ended
└─ InnoDB 스토리지 엔진 초기화 (약 0.24초)
06:05:13 [MY-013602] Channel mysql_main configured to support TLS
└─ TLS/SSL 채널 설정 완료
06:05:13 [MY-011323] X Plugin ready for connections (port 33060)
└─ X Protocol 준비 완료 (MySQL Shell 등에서 사용)
06:05:13 [MY-010931] ready for connections (port 13306)
└─ mysqld 완전 기동 완료 ← 정상화 판단 기준점
2번 장애(OOM Kill)
참고
- OOM Kill은 systemd가 없으므로 커널이 mysqld를 직접 죽이게 해야 하는데, stress-ng나 INSERT 루프보다 kill -9 로 간단히 연출하고 error log 패턴만 확인하는 게 효율적
- OOM 기록은 dmesg에만 찍히고 error log에는 mysqld_safe의 감지 메시지만 남음
# mysqld PID 확인
cat /home1/irteam/mysql/run/mysql.pid
# SIGKILL 전송 (OOM Kill과 동일한 효과)
kill -9 $(cat /home1/irteam/mysql/run/mysql.pid)
# mysqld_safe가 재시작할 때까지 대기 후 로그 확인
sleep 10 && tail -20 /home1/irteam/mysql/log/mysql.err
결과
kill -9 (OOM Kill 동일 패턴) 로그 흐름 정리
06:14:05 mysqld_safe Number of processes running now: 0
└─ mysqld 프로세스가 사라진 것을 mysqld_safe가 감지
← [CRASH_DETECTED] 감지 기준점
06:14:05 mysqld_safe mysqld restarted
└─ mysqld_safe가 자동 재시작 결정
(SIGTERM과 달리 SIGKILL은 비정상 종료로 인식 → 재시작)
06:14:05 [MY-010116] mysqld starting as process 2161286
└─ 새 mysqld 프로세스 생성
06:14:05 [MY-013576] InnoDB initialization has started
06:14:05 [MY-013577] InnoDB initialization has ended
06:14:05 [MY-010229] Starting XA crash recovery...
06:14:06 [MY-010232] XA crash recovery finished.
└─ 정상 종료와의 핵심 차이점
비정상 종료 시에만 등장 → 비정상 종료의 간접 증거
06:14:06 [MY-010931] ready for connections
└─ 재시작 완료 ← 정상화 판단 기준점
정상 종료 vs 비정상 종료(kill -9) 차이:
| 항목 | 정상 종료 (SIGTERM) | 비정상 종료 (SIGKILL/OOM) |
| Received SHUTDOWN | ✓ | ✗ |
| Shutdown complete | ✓ | ✗ |
| mysqld_safe ... ended | ✓ | ✗ |
| Number of processes running now: 0 | ✗ | ✓ |
| mysqld restarted | ✗ | ✓ |
| XA crash recovery | ✗ | ✓ |
=> [CRASH_DETECTED]의 감지 키워드로 Number of processes running now: 0 만 사용해도 됨
3번 장애(too many connections)
현재 max_connections 설정값 확인
/home1/irteam/mysql/base/bin/mysql \
-S /home1/irteam/mysql/run/mysql.sock \
-u root -p'비밀번호' \
-e "SHOW VARIABLES LIKE 'max_connections';"
결과: max_connections = 151
# 1. max_connections를 3으로 낮춤 (root + 테스트 연결 고려)
/home1/irteam/mysql/base/bin/mysql \
-S /home1/irteam/mysql/run/mysql.sock \
-u root -p'nhn!@#123' \
-e "SET GLOBAL max_connections = 3;"
# 2. 연결 폭발 (백그라운드로 10개 연결 동시 시도)
for i in $(seq 1 10); do
/home1/irteam/mysql/base/bin/mysql \
-S /home1/irteam/mysql/run/mysql.sock \
-u root -p'nhn!@#123' \
-e "SELECT SLEEP(10);" &
done
# 3. 잠시 대기 후 로그 확인
sleep 5 && tail -20 /home1/irteam/mysql/log/mysql.err
결과

Too many connections 에러가 클라이언트 측(터미널)에는 출력됐지만 error log에는 아무것도 찍히지 않음
log_error_verbosity 값 확인
확인 결과: log_error_verbosity = 2
3이어야 Too many connections도 로그파일에 기록되지만 실제 운영 환경에서 log_error_verbosity가 3인 경우는 흔치 않음(로그가 너무 많이 쌓여 디스크에 부담이 되기 때문)
결론
=> Too many connections는 스킵하자
max_connections 초과는 DB 자체 장애라기보다 애플리케이션 레벨 문제이기도 하고, error log에 흔적이 남지 않는 장애를 수집하는 건 나중에 구현 진행해도 됨
max_connections를 원래대로 복구
/home1/irteam/mysql/base/bin/mysql \
-S /home1/irteam/mysql/run/mysql.sock \
-u root -p'비밀번호' \
-e "SET GLOBAL max_connections = 151;"
4번 장애(디스크 full)
디스크 여유 공간 확인
df -h /home1/irteam/mysql/data
결과: 여유 공간이 56G로 넉넉해서 전부 채우는 건 비효율적
MySQL 데이터 디렉토리를 별도 작은 파티션으로 마운트하는 대신, fallocate로 큰 파일을 만들어 공간을 채우기
- 56G 중 50G는 실제 데이터 없이 공간만 점유하도록 해, 6G만 다 채워도 디스크 full이 일어나도록 설계함
- MySQL 쓰기 흐름 (INSERT 실행 시): 클라이언트 → mysqld → InnoDB → t.ibd 파일에 데이터 기록 → binlog 파일에 변경 이력 기록
- insert 명령 시 쓰이는 information_schema.tables은 MySQL 내장 가상 테이블로 항상 존재함. 테스트 목적으로 대량 행을 빠르게 생성할 때 자주 쓰임
# 1. 50G짜리 더미 파일 생성 (약 몇 초 소요)
fallocate -l 50G /home1/irteam/dummy_fill.img
# 2. 디스크 여유 공간 확인 (얼마 안 남았는지 확인)
df -h /home1/irteam/mysql/data
# 3. MySQL에서 쓰기 작업 유발 (binlog 쓰기 트리거)
/home1/irteam/mysql/base/bin/mysql \
-S /home1/irteam/mysql/run/mysql.sock \
-u root -p'비밀번호' \
-e "CREATE DATABASE IF NOT EXISTS test_disk;
USE test_disk;
CREATE TABLE IF NOT EXISTS t (id INT AUTO_INCREMENT PRIMARY KEY, v VARCHAR(255));
INSERT INTO t (v) SELECT REPEAT('x', 255) FROM information_schema.tables LIMIT 100;"
# 4. 로그 확인
tail -20 /home1/irteam/mysql/log/mysql.err
=> 디스크 full 연출은 실패
참고
df -h: 파일시스템 전체 여유 공간
du -sh: MySQL 데이터 디렉토리가 현재 차지하는 크기
MySQL 데이터를 꽉 채워 df -h의 Avail 용량을 0으로 만들면 디스크 Full 장애 발생
시행착오 후 재시도
# 1. my.cnf에 O_DIRECT 추가 (캐시 우회 쓰기)
echo "innodb_flush_method=O_DIRECT" >> /home1/irteam/mysql/my.cnf
# 2. MySQL 재시작
kill $(cat /home1/irteam/mysql/run/mysql.pid)
sleep 3
nohup /home1/irteam/mysql/base/bin/mysqld_safe \
--defaults-file=/home1/irteam/mysql/my.cnf > /dev/null 2>&1 &
sleep 5
# 3. 설정 확인
/home1/irteam/mysql/base/bin/mysql \
-S /home1/irteam/mysql/run/mysql.sock \
-u root -p'비밀번호' \
-e "SHOW VARIABLES LIKE 'innodb_flush_method';"
# 4. 페이지 캐시 다시 비우기
sync && echo 3 | sudo tee /proc/sys/vm/drop_caches
# 5. 대량 INSERT + 실시간 로그 모니터링 (별도 터미널에서)
tail -f /home1/irteam/mysql/log/mysql.err
# 별도 터미널에서 INSERT 실행
/home1/irteam/mysql/base/bin/mysql \
-S /home1/irteam/mysql/run/mysql.sock \
-u root -p'비밀번호' \
-e "USE test_disk;
INSERT INTO t (v) SELECT REPEAT('x', 255)
FROM information_schema.tables a,
information_schema.tables b,
information_schema.tables c LIMIT 500000;"
=> 에러 메시지가 잘림 -> 디스크가 꽉 차서 로그 파일 자체도 못 쓰는 상황. 디스크 full 장애 연출 성공!
최종 확인
# 1. mysqld 프로세스 살아있는지 확인
ps aux | grep mysqld | grep -v grep
# 2. 로그 전체 마지막 부분
tail -10 /home1/irteam/mysql/log/mysql.err
# 3. dmesg에서 디스크 관련 에러 확인
sudo dmesg | tail -20
결론
| 항목 | 결과 |
| 디스크 Full 직전 증상 | [MY-014084] redo log 병목 → 수집 가능 |
| 디스크 Full 직접 에러 | [MY-000??] 로그가 잘려서 메시지 코드 확인 불가 |
| 로그 기록 자체 | 디스크 Full이면 로그도 못 씀 |
디스크 full이면 로그가 잘리는 상황이므로 로그 내용을 수집할 수 없음
원상 복구
# 1. 더미 파일 정리
rm -f /home1/irteam/dummy*.img
# 2. 디스크 상태 확인
df -h /home1/irteam/mysql/data
# 3. my.cnf에서 O_DIRECT 제거
sed -i '/innodb_flush_method/d' /home1/irteam/mysql/my.cnf
디스크 full 장애 상황도 수집하도록 스크립트에 반영
디스크 full이면 무조건 로그가 잘리나? -> 은빈 인턴님은 디스크 full 연출 시 로그가 잘리지 않았다고 함
스크립트 코드 구현은 일단 은빈 인턴님이 디스크 full 장애를 내고 기록된 로그를 바탕으로 진행함
디스크 full 로그 패턴 흐름
22:56:46 [MY-014084] Threads are unable to reserve space in redo log
└─ 디스크 부족으로 redo log checkpoint 불가 (전조 증상)
22:56:47 [MY-013865] Redo log writer is waiting for a new redo log file
└─ redo log 공간 부족 (전조 증상)
22:56:48 [MY-000035] Disk is full writing './mysql-bin.000016'
(OS errno 28 - No space left on device).
Waiting for someone to free space... Retry in 60 secs.
└─ 디스크 Full 직접 감지. 60초마다 재시도하며 대기
22:59:44 [MY-010907] Error writing file 'mysql-bin' (errno: 28)
└─ 60초 대기 후 재시도에서도 실패
22:59:44 [MY-011072] Binary logging not possible.
'binlog_error_action' is set to 'ABORT_SERVER'.
Server is being stopped.
└─ binlog 쓰기 포기, ABORT_SERVER 발동
22:59:44 mysqld got signal 6
handle_fatal_signal ← [SEGFAULT] 감지 키워드
exec_binlog_error_action_abort
└─ mysqld 스스로 SIGABRT 발생 후 강제 종료
22:59:50 mysqld_safe Number of processes running now: 0 ← [CRASH_DETECTED]
22:59:50 mysqld_safe mysqld restarted
22:59:50 [MY-010116] starting as process ...
22:59:51 [MY-013577] InnoDB initialization has ended
22:59:51 [MY-010229] Starting XA crash recovery...
22:59:51 [MY-010232] XA crash recovery finished.
22:59:51 [MY-010931] ready for connections ← 정상화 기준점
5번 장애(segfault)
# 1. Segfault 연출 (SIGSEGV 전송)
kill -SIGSEGV $(cat /home1/irteam/mysql/run/mysql.pid)
# 2. mysqld_safe가 재시작할 때까지 대기 후 로그 확인
sleep 10 && tail -30 /home1/irteam/mysql/log/mysql.err
Segfault 로그 흐름 정리
08:05:43 Attempting backtrace. You can use the following information...
stack_bottom = 0 thread_stack 0x100000
#0 0x101ac96 _Z18print_fatal_signali ...
#1 0x101ad54 handle_fatal_signal ...
... ← 스택 트레이스 (여러 줄)
The manual page at http://dev.mysql.com/...
08:05:43 mysqld_safe Number of processes running now: 0 ← [CRASH_DETECTED]
08:05:43 mysqld_safe mysqld restarted ← [SAFE_RESTARTED]
08:05:43 [MY-010116] starting as process 2164903 ← [STARTING]
08:05:43 [MY-013576] InnoDB initialization has started
08:05:44 [MY-013577] InnoDB initialization has ended ← [INNODB_READY]
08:05:44 [MY-010229] Starting XA crash recovery... ← [XA_RECOVERY]
08:05:44 [MY-010232] XA crash recovery finished. ← [XA_RECOVERY_END]
08:05:44 [MY-010931] ready for connections ← [READY] 정상화 기준점
=> Segfault 시 Aborting 메시지나 [SEGFAULT] 키워드가 error log에 찍히지 않음
스택 트레이스(Attempting backtrace)와 handle_fatal_signal이 Segfault의 실제 감지 키워드
스택 트레이스란?
서버가 예상치 못하게 종료(crash)되었을 때 에러 로그 파일에 기록되는 함수 호출 경로 정보(어떤 경로를 거쳐 호출됐는지, 어느 함수를 호출하는 도중에 오류가 발생했는지 파악할 수 있음)
스택 트레이스를 제외하면 kill -9와 로그 패턴이 동일하므로, 구현에 용이
| 항목 | kill -9 | SIGSEGV |
| 스택 트레이스 | ✗ | ✓ |
| Number of processes running now: 0 | ✓ | ✓ |
| mysqld restarted | ✓ | ✓ |
| XA crash recovery | ✓ | ✓ |
| ready for connections | ✓ | ✓ |
| 태그 | 감지 키워드 | 비고 |
| [SEGFAULT] | handle_fatal_signal | 스택 트레이스 첫 줄에 등장 |
| [CRASH_DETECTED] | mysqld_safe Number of processes running now: 0 | Segfault/OOM/kill -9 공통 |
6번 장애(복제 연결 단절 - 마스터 재시작)
ca801(마스터) 재시작 시 cb801(레플리카) 로그에 어떤 패턴이 찍히는지 확인
ca801에서
# 마스터 재시작
kill $(cat /home1/irteam/mysql/run/mysql.pid)
sleep 3
nohup /home1/irteam/mysql/base/bin/mysqld_safe \
--defaults-file=/home1/irteam/mysql/my.cnf > /dev/null 2>&1 &
cb801에서
# 레플리카 로그 실시간 모니터링
tail -f /home1/irteam/mysql/log/mysql.err
로그 패턴 정리
08:05:43 [MY-010557] Error reading packet from server: Lost connection
└─ 마스터가 갑자기 죽으면서 복제 연결 끊김 ← [CONN_LOST]
08:05:43 [MY-010897] Storing MySQL user name... (Warning)
└─ 재연결 시도 전 경고, 노이즈 → 수집 불필요
08:05:43 [MY-010584] Error reconnecting to source, attempt 1/86400
└─ 재연결 시도 중 ← [RECONNECTING] (첫/마지막만 표시)
08:06:43 [MY-010592] connected to source, replication resumed
└─ 복제 재연결 완료 ← [CONNECTED] 정상화 기준점
08:06:43 [MY-014001] connected to source, Starting replication from file
└─ 복제 스레드 시작 ← [REPL_START]
08:11:39 [MY-010558] received end packet from server due to dump thread
being killed on source
└─ 마스터가 재시작되면서 dump thread가 종료됨
새로운 패턴(마스터 정상 종료 상황)이지만 마스터 비정상 종료 상황과 동일한 태그 사용 ← [CONN_LOST]
08:12:39 [MY-010592] connected to source, replication resumed
└─ 복제 재연결 완료 ← [CONNECTED] 정상화 기준점
08:12:39 [MY-014001] connected to source, Starting replication from file
└─ 복제 스레드 시작 ← [REPL_START]
7번 장애(복제 연결 단절 - 네트워크 단절)
iptables로 ca801↔cb801 포트를 차단/해제하기
ca801에서
# cb801 IP 확인
echo "cb801 IP 확인"
grep replica /home1/irteam/mysql/my.cnf || echo "cb801주소"
cb801에서
# ca801 IP 확인 (로그에서 직접)
grep "connected to source" /home1/irteam/mysql/log/mysql.err | tail -1
cb801에서
로그 모니터링
tail -f /home1/irteam/mysql/log/mysql.err
ca801에서
# 1. 포트 차단
sudo iptables -I INPUT -s cb801주소 -p tcp --dport 13306 -j DROP
echo "차단 시작: $(date)"
# 2. 90초 대기 (replica_net_timeout 60초 + 여유 30초)
sleep 90
# 3. 차단 해제
sudo iptables -D INPUT -s cb801주소 -p tcp --dport 13306 -j DROP
echo "차단 해제: $(date)"
로그 패턴 분석
08:29:45 [MY-010897] Warning ← 차단 후 60초 뒤 재연결 시도 (08:28:16 + 60초 = 08:29:16 근처)
08:30:05 connected to source ← 차단 해제 후 재연결 성공
=> [CONN_LOST] 패턴이 없음
원인 추측
- DROP은 패킷을 조용히 버리는 방식이라 TCP 연결이 즉시 끊기지 않고 타임아웃까지 기다림
- 그 사이 replica_net_timeout(60초)이 지나면 레플리카가 스스로 재연결을 시도하는데, 이 경우 Lost connection 대신 Warning만 찍히고 넘어갈 수 있음
재시도(ca801에서)
# DROP 대신 REJECT 사용 (즉시 RST 패킷 전송)
sudo iptables -I INPUT -s cb801주소 -p tcp --dport 13306 -j REJECT
echo "차단 시작: $(date)"
sleep 90
sudo iptables -D INPUT -s cb801주소 -p tcp --dport 13306 -j REJECT
echo "차단 해제: $(date)"
로그 패턴 정리
08:32:15 iptables REJECT 차단 시작
│
│ (replica_net_timeout 60초 대기)
│
08:33:35 [MY-010897] Warning ← 재연결 시도 전 경고
08:33:35 [MY-010584] Error reconnecting ← 재연결 실패 (REJECT로 즉시 거부)
│
│ (60초 후 재시도)
│
08:34:03 iptables REJECT 해제
08:34:35 [MY-010592] connected to source ← 재연결 성공
08:34:35 [MY-014001] Starting replication
=> 이번에도 [CONN_LOST] 로그는 안 찍힘
복제 구성 로그 패턴 정리:
| 상황 | 찍히는 패턴 |
| 마스터 비정상 종료(kill -9) | [MY-010557] → [MY-010584] → [MY-010592] |
| 마스터 정상 종료(SIGTERM) | [MY-010558] → [MY-010584] → [MY-010592] |
| 네트워크 차단(REJECT) | [MY-010584] → [MY-010592] |
| 네트워크 차단(DROP) | Warning만 → [MY-010592] |
[CONN_LOST] 감지 키워드
| 태그 | 감지 키워드 | 상황 |
| [CONN_LOST] | [MY-010557] | 마스터 비정상 종료 / 네트워크 강제 단절 |
| [CONN_LOST] | [MY-010558] | 마스터 정상 종료 |
| [RECONNECTING] | [MY-010584] | 재연결 시도 중 (첫/마지막만 표시) |
| [CONNECTED] | [MY-010592] | 재연결 성공 정상화 기준점 |
| [REPL_START] | [MY-014001] | 복제 스레드 시작 |
8번 장애(마스터-레플리카 간 데이터 정합성 장애)
레플리카에서 직접 데이터를 수정한 뒤 마스터에서 동일 row를 건드려 충돌 유발
cb801에서 실행 (복제 일시 중단 + 데이터 직접 수정)
/home1/irteam/mysql/base/bin/mysql \
-S /home1/irteam/mysql/run/mysql.sock \
-u root -p'비밀번호' \
-e "STOP REPLICA SQL_THREAD;
USE test_disk;
INSERT INTO t VALUES (99999, 'replica_only_data');"
ca801에서 실행 (마스터에서 동일 pk insert)
/home1/irteam/mysql/base/bin/mysql \
-S /home1/irteam/mysql/run/mysql.sock \
-u root -p'비밀번호' \
-e "USE test_disk;
INSERT INTO t VALUES (99999, 'master_data');"
cb801에서 복제 재개 후 로그 확인
/home1/irteam/mysql/base/bin/mysql \
-S /home1/irteam/mysql/run/mysql.sock \
-u root -p'비밀번호' \
-e "START REPLICA SQL_THREAD;"
sleep 3
tail -20 /home1/irteam/mysql/log/mysql.err
결과
cb801에서 INSERT INTO t VALUES (99999, 'replica_only_data')가 Duplicate entry 에러로 실패
=> 99999는 이미 존재
하지만 mysql.err 로그를 확인한 결과, 정합성 충돌은 error log에 기록되지 않는 것이 확인됨
8번 장애는 스크립트에 반영하지 않음
9번 장애(레플리카의 디스크 Full 장애)
마스터의 데이터를 레플리카가 동기화하는 과정에서 레플리카의 디스크 용량을 부족하게 설정
터미널 1 - cb801에서 실행 (로그 모니터링):
tail -f /home1/irteam/mysql/log/mysql.err
터미널 2 - cb801에서 실행 (디스크 채우기):
fallocate -l 37G /home1/irteam/dummy.img && df -h /home1/irteam/mysql/data
터미널 3 - ca801에서 실행 (대량 INSERT로 복제 유발):
/home1/irteam/mysql/base/bin/mysql \
-S /home1/irteam/mysql/run/mysql.sock \
-u root -p'비밀번호' \
-e "USE test_disk;
INSERT INTO t (v) SELECT REPEAT('x', 255)
FROM information_schema.tables a,
information_schema.tables b,
information_schema.tables c LIMIT 500000;"
결과
=> 새로운 로그가 확인됨. 레플리카(cb801)의 Avail 용량도 0임이 확인됨
로그 패턴 흐름 정리(레플리카(cb801) 기준)
02:21:45 [MY-014084] redo log 공간 부족 (전조)
02:21:46 [MY-012144] posix_fallocate() failed: No space left on device
└─ InnoDB가 t.ibd 파일 확장 시도 실패
02:21:46 [MY-012637] 일부만 기록됨 (880640/1048576 bytes)
02:21:46 [MY-012638] 재시도 실패
02:21:46 [MY-012639] Write to file failed, OS errno 28
02:21:46 [MY-012640] Error number 28 = 'No space left on device'
02:21:46 [MY-012145] t.ibd 쓰기 실패
02:21:47 [MY-013132] The table 't' is full!
02:21:47 [MY-010584] Replica SQL Worker 1 failed
└─ 복제 SQL 스레드 중단
(이후 로그 잘림)
마스터 디스크 Full과의 차이:
| 항목 | 마스터 디스크 Full | 레플리카 디스크 Full |
| 핵심 키워드 | [MY-000035], [MY-011072] | [MY-012144], [MY-013132], [MY-010584] |
| mysqld 종료 여부 | ✓ ABORT_SERVER로 강제 종료 | ✗ mysqld는 살아있음 |
| 복제 중단 여부 | ✓ (마스터 종료로 연결 끊김) | ✓ SQL 스레드만 중단 |
| 자동 복구 | mysqld_safe가 재시작 | 디스크 확보 후 수동 START REPLICA SQL_THREAD 필요 |
복구 진행
# 1. 더미 파일 삭제로 공간 확보
rm /home1/irteam/dummy.img
df -h /home1/irteam/mysql/data
# 2. 복제 SQL 스레드 재시작
/home1/irteam/mysql/base/bin/mysql \
-S /home1/irteam/mysql/run/mysql.sock \
-u root -p'비밀번호' \
-e "START REPLICA SQL_THREAD;"
# 3. 복제 상태 확인
/home1/irteam/mysql/base/bin/mysql \
-S /home1/irteam/mysql/run/mysql.sock \
-u root -p'비밀번호' \
-e "SHOW REPLICA STATUS\G" | grep -E "Slave_SQL_Running|Seconds_Behind|Last_SQL_Error"
복구 후 로그 흐름 정리
cb801 로그 흐름:
02:21:46 [MY-012144] posix_fallocate() failed: No space left on device
02:21:46 [MY-012639] Write to file failed, errno 28
02:21:46 [MY-012640] Error number 28 = 'No space left on device'
02:21:47 [MY-013132] The table 't' is full!
02:21:47 [MY-010584] Replica SQL Worker 1 failed ← SQL 스레드 중단, 로그 잘림
※ 더미 파일 삭제 후 공간 확보
02:28:29 [MY-014084] redo log 공간 부족 (복제 재개 후 밀린 데이터 처리 중)
02:29:11 [MY-010557] Lost connection ← ca801 redo log 병목으로 인한 마스터 재시작 또는 연결 끊김
02:29:11 [MY-014001] connected to source, Starting replication ← 복제 재연결
ca801 로그 흐름:
02:21:38 [MY-014084] redo log 병목 (INSERT 처리 중)
02:22:06 [MY-014084] redo log 병목 지속
=> ca801은 mysqld가 종료되지 않았고, INSERT가 완료된 후 redo log 병목만 찍힘
레플리카 디스크 Full 패턴 확정:
| 키워드 | 의미 |
| [MY-012144] | InnoDB 파일 확장 실패 (No space left) |
| [MY-012639] | 파일 쓰기 실패 (errno 28) |
| [MY-012640] | errno 28 = No space left on device |
| [MY-013132] | The table is full |
| [MY-010584] | Replica SQL Worker 실패 → SQL 스레드 중단 |
9번 장애 재시도(레플리카의 디스크 Full 장애를 감지하기 위해)
ca801에서 실행 (대량 INSERT로 복제 유발):
/home1/irteam/mysql/base/bin/mysql \
-S /home1/irteam/mysql/run/mysql.sock \
-u root -p'비밀번호' \
-e "USE test_disk;
INSERT INTO t (v) SELECT REPEAT('x', 255)
FROM information_schema.tables a,
information_schema.tables b,
information_schema.tables c LIMIT 500000;"
로그 패턴 정리
06:52:17 [MY-000035] Disk is full writing './relay-bin.000043'
Waiting for someone to free space... Retry in 60 secs
07:02:17 [MY-000035] (600초마다 반복 출력)
07:12:18 [MY-000035] (반복)
07:22:18 [MY-000035] (반복)
※ 공간 확보 시 자동 재개 (mysqld 종료 없음)
이전 레플리카 디스크 Full과 비교:
| 항목 | InnoDB 파일 쓰기 실패 | relay-bin 쓰기 실패 |
| 핵심 키워드 | [MY-012144], [MY-013132] | [MY-000035] |
| 대상 파일 | t.ibd (데이터 파일) | relay-bin.xxxxx |
| mysqld 종료 | ✗ | ✗ |
| 복제 중단 | SQL 스레드 즉시 중단 | I/O 스레드 대기 (자동 재개 가능) |
| 복구 방식 | 수동 START REPLICA SQL_THREAD | 공간 확보 시 자동 재개 |
현재 스크립트는 relay-bin 쓰기 실패 로그 패턴에 대한 장애 감지가 안되는 상황
=> 코드 수정 진행
주요 수정 사항: 정상화 판단 기준(gap)을 12분으로 수정
이유: 디스크 full 에러 메시지([MY-000035])가 10분에 한번씩 출력되기 때문
레플리카 디스크 Full 장애 감지 완료

'인턴' 카테고리의 다른 글
| [장애 이력 자동 작성 도구 16] Redis, MySQL 추가 고민 (0) | 2026.03.12 |
|---|---|
| [장애 이력 자동 작성 도구 15] MySQL 시행착오 (0) | 2026.03.12 |
| [장애 이력 자동 작성 도구 13] MySQL 최종 정리 (0) | 2026.03.12 |
| [장애 이력 자동 작성 도구12] Redis 스크립트 추가 고도화 (0) | 2026.03.10 |
| [장애 이력 자동 작성 도구11] Redis 복제 구조 장애 상황 연출 및 로그 수집 코드 구현 (0) | 2026.03.10 |