개요
컴퓨터를 껏다가 키는 동작을 여러 날 시겼으며,
잘 동작하던 MySQL 파드가 어느날 갑자기 동작하지 않았습니다.
복구 설차를 설명 합니다.
진단 및 해결절차
로그를 보면 innoDB 엔진 초기화가 안되는데, 데이터 파일에 문제가 생긴듯 하다.
"""
mysql 05:51:19.18 INFO ==> Starting mysql in background
2025-07-28T05:51:19.188987Z 0 [System] [MY-015015] [Server] MySQL Server - start.
2025-07-28T05:51:19.389196Z 0 [System] [MY-010116] [Server] /opt/bitnami/mysql/bin/mysqld (mysqld 9.3.0) starting as process 38
2025-07-28T05:51:19.391364Z 0 [Warning] [MY-013242] [Server] --character-set-server: 'utf8' is currently an alias for the character set UTF8MB3, but will be an alias for UTF8MB4 in a future release. Please consider using UTF8MB4 in order to be unambiguous.
2025-07-28T05:51:19.394161Z 1 [System] [MY-013576] [InnoDB] InnoDB initialization has started.
2025-07-28T05:51:19.589469Z 1 [ERROR] [MY-012960] [InnoDB] Cannot create redo log files because data files are corrupt or the database was not shut down cleanly after creating the data files.
2025-07-28T05:51:19.589512Z 1 [ERROR] [MY-012930] [InnoDB] Plugin initialization aborted with error Generic error.
2025-07-28T05:51:19.933979Z 1 [ERROR] [MY-010334] [Server] Failed to initialize DD Storage Engine
2025-07-28T05:51:19.934131Z 0 [ERROR] [MY-010020] [Server] Data Dictionary initialization failed.
2025-07-28T05:51:19.934155Z 0 [ERROR] [MY-010119] [Server] Aborting
2025-07-28T05:51:19.935204Z 0 [System] [MY-010910] [Server] /opt/bitnami/mysql/bin/mysqld: Shutdown complete (mysqld 9.3.0) Source distribution.
2025-07-28T05:51:19.935221Z 0 [System] [MY-015016] [Server] MySQL Server - end.
"""
스테이트 풀셋을 리클리카를 0으로 하고, 디스크를 정상적인 파드를 마운트해서 체크해 봐야 하겠다.
"""
kubectl run debug-pod \
--image=bitnami/minideb \
--namespace=coinauto \
--overrides='
{
"apiVersion": "v1",
"spec": {
"volumes": [
{
"name": "mysql-data",
"persistentVolumeClaim": {
"claimName": "data-mysql-0"
}
}
],
"containers": [
{
"name": "debug",
"image": "bitnami/minideb",
"command": ["sleep", "3600"],
"volumeMounts": [
{
"mountPath": "/data",
"name": "mysql-data"
}
]
}
],
"restartPolicy": "Never"
}
}'
"""
진단용 파드로 파일 리스트를 체크해 봅니다.
binlog.index 파일 크기 0인상태인데, 비정상 종료시 흔하게 일어나는 현상으로 복구를 시도해야 하는 상황 입니다.
root@debug-pod:/data# du -sh /data/data/*
6.0M /data/data/#ib_16384_0.dblwr
14M /data/data/#ib_16384_1.dblwr
101M /data/data/#innodb_redo
804K /data/data/#innodb_temp
4.0K /data/data/auto.cnf
0 /data/data/binlog.index
12M /data/data/ibdata1
12M /data/data/ibtmp1
4.0K /data/data/mysql
980K /data/data/mysql.ibd
16M /data/data/undo_001
16M /data/data/undo_002
파일을 로컬로 복사해 놓자
kubectl cp coinauto/debug-mysql:/data/data ./mysql_recovery
그리고 도커로 해당 파일로 마운트 합니다.
docker run -it --rm \
-v ./mysql_recovery:/var/lib/mysql \
--entrypoint /bin/bash \
mysql:9.3.0
파일확인 합니다.
bash-5.1# cd /var/lib/mysql
bash-5.1# ls -al
새로운 정상적인 SQL 도커를 실행 합니다.
docker run -it --rm \
--name mysql-recover \
-v ./mysql_clean:/var/lib/mysql \
-e MYSQL_ROOT_PASSWORD=admin1234 \
mysql:8.0
새로운 정상적인 SQL 도커에 접속
docker exec -it mysql-recover mysql -uroot -padmin1234
DB작업
CREATE DATABASE mydb;
USE mydb;
테이블 작업
-- 1. trades 테이블 생성
CREATE TABLE IF NOT EXISTS trades (
id INT AUTO_INCREMENT PRIMARY KEY,
timestamp DATETIME,
action VARCHAR(10),
entry_price DOUBLE,
amount DOUBLE,
order_size DOUBLE,
leverage INT,
stop_loss DOUBLE,
take_profit DOUBLE,
kelly_fraction DOUBLE,
win_probability DOUBLE,
volatility DOUBLE,
status VARCHAR(10) DEFAULT 'open'
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
-- 2. trade_results 테이블 생성
CREATE TABLE IF NOT EXISTS trade_results (
id INT AUTO_INCREMENT PRIMARY KEY,
trade_id INT,
close_timestamp DATETIME,
close_price DOUBLE,
pnl DOUBLE,
pnl_percentage DOUBLE,
duration VARCHAR(50),
result VARCHAR(20),
FOREIGN KEY (trade_id) REFERENCES trades(id)
ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
-- 3. account_history 테이블 생성
CREATE TABLE IF NOT EXISTS account_history (
id INT AUTO_INCREMENT PRIMARY KEY,
timestamp DATETIME,
balance DOUBLE,
equity DOUBLE,
unrealized_pnl DOUBLE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
테이블 내용 지우기
ALTER TABLE trades DISCARD TABLESPACE;
ALTER TABLE trade_results DISCARD TABLESPACE;
ALTER TABLE account_history DISCARD TABLESPACE;
.ibd 파일 복사 : 호스트 OS에서 .ibd 파일을 복사하여 컨테이너 내부에 덮어씌웁니다:
docker cp ./mysql_recovery/mydb/users.ibd mysql-recover:/var/lib/mysql/mydb/users.ibd
권한 맞추기
docker exec -it mysql-recover bash -c "chown mysql:mysql /var/lib/mysql/mydb/users.ibd"
테이블스페이스 가져오기
-- 다시 MySQL 접속
USE mydb;
ALTER TABLE trades IMPORT TABLESPACE;
ALTER TABLE trade_results IMPORT TABLESPACE;
ALTER TABLE account_history IMPORT TABLESPACE;
데이터 확인
SELECT * FROM trades;
SELECT * FROM trade_results;
SELECT * FROM account_history;
✅ 주요 원인과 대응 방안
1. 컨테이너 강제 종료 (docker kill, 시스템 다운 등)
원인
컨테이너가 SIGKILL로 종료되면 MySQL은 버퍼에 있던 데이터를 디스크에 flush하지 못합니다.
이로 인해 ibdata1, *.ibd, undo_log, redo_log 파일 불일치 발생 → 복구 어려움.
예방
반드시 **docker stop**으로 정상 종료하도록 합니다.
종료 전 FLUSH TABLES WITH READ LOCK 등으로 동기화 시도 가능.
2. tmpfs, overlayFS, bind mount로 인한 flush 실패
원인
일부 스토리지 드라이버는 MySQL의 fsync, fdatasync() 요청을 무시하거나 느리게 처리.
특히 aufs, overlay2, tmpfs 등에서 문제가 발생하기도 함.
예방
반드시 -v /data/mysql:/var/lib/mysql 처럼 직접적인 host volume mount 사용.
Longhorn, EBS, GCE Persistent Disk 등 정식 블록 스토리지를 마운트하는 것이 가장 안정적.
3. 도커 환경에서 MySQL 설정값 부족
원인
innodb_flush_method, innodb_log_file_size, sync_binlog 등의 설정이 기본값이면 장애에 매우 취약.
예방 (추천 my.cnf 설정):
ini
복사
편집
[mysqld]
innodb_flush_method=O_DIRECT
innodb_flush_log_at_trx_commit=1
sync_binlog=1
flush_method=O_DIRECT는 버퍼를 우회하여 디스크에 직접 기록, 더 안전.
하루 1회 안전 종료/재시작을 위한 Job 구성
안전 종료 절차 요약
MySQL 내부에 접속
FLUSH TABLES WITH READ LOCK
mysqladmin shutdown 호출
Pod가 재시작되도록 트리거
Kubernetes CronJob 예제
apiVersion: batch/v1
kind: CronJob
metadata:
name: mysql-daily-restart
namespace: default
spec:
schedule: "0 4 * * *" # 매일 새벽 4시
jobTemplate:
spec:
template:
spec:
containers:
- name: shutdown
image: mysql:8.0
command:
- /bin/bash
- -c
- |
echo "[INFO] Attempting MySQL shutdown"
mysql -h my-mysql.default.svc.cluster.local -uroot -padmin1234 -e "FLUSH TABLES WITH READ LOCK;"
mysqladmin -h my-mysql.default.svc.cluster.local -uroot -padmin1234 shutdown
restartPolicy: Never
파드 재기동
kubectl rollout restart statefulset my-mysql
preStop Hook으로 종료 시 flush 처리 추가 (안정성 추가)
lifecycle:
preStop:
exec:
command:
- /bin/bash
- -c
- |
mysql -uroot -p$MYSQL_ROOT_PASSWORD -e "FLUSH TABLES WITH READ LOCK;"
sleep 10
암호시크릿 만들기
kubectl create secret generic mysql-secret \
--from-literal=MYSQL_ROOT_PASSWORD=admin1234 -n coinauto
댓글
댓글 쓰기