1️⃣ 상황 요약 (Situation)
환경: InnoDB 기반 운영 DB / 수천만 Row
증상: 쿼리 대기 폭증, 세션 정체, 서비스 응답 급락
영향: 전체 트랜잭션 처리량 급락, 장애 전조 발생
DELETE FROM CQ_SHORT_INFO;
2️⃣ 즉시 확인 (Quick Check)
SHOW ENGINE INNODB STATUS;
-- MySQL 5.7 / MariaDB
SELECT * FROM information_schema.innodb_locks;
SELECT * FROM information_schema.innodb_lock_waits;
-- MySQL 8.0+
SELECT * FROM performance_schema.data_locks;
3️⃣ 원인 분석 (Root Cause)
DELETE는 단순 삭제가 아니다.
대규모 Undo Log + Redo I/O + Row-Level Exclusive Lock이 동시에 발생하는 부하가 많이 걸리는 작업이다.
4️⃣ 기본 조치 (Resolution — Standard Pattern)
대량 DELETE는 반드시 배치로 나눈다.
운영 기준
- 배치 사이즈: 1,000 ~ 10,000
- 단일 트랜잭션 대량 DELETE 금지
Replication 주의
binlog_format = STATEMENT→DELETE ... LIMIT
비결정적 위험
=> Master와 Slave가 서로 다른 데이터를 지울 수 있음ROW/MIXED사용 권장
Foreign Key 사전 점검
ON DELETE CASCADE존재 시
배치 사이즈 ≤ 1,000
5️⃣ 심화 전략 (Advanced Strategies)
🅐 Copy & Swap 패턴 (대량 삭제의 정석)
지우는 비용보다 새로 만드는 비용이 싸다.
절차
- 동일 스키마
NEW_CQ_SHORT_INFO생성 - [필수 안전 장치 — 트랜잭션 격리 수준 변경]
SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
[필독]
기본REPEATABLE READ에서는
복사 중 원본 테이블에 S-Lock 발생 → 쓰기 차단 발생 :
위험: 기본 설정(REPEATABLE READ)에서는 복사 중 원본 테이블에 S-Lock이 걸려 모든 쓰기(INSERT/UPDATE/DELETE)가 전면 차단된다.해결: 위 명령어로 격리 수준을
READ COMMITTED로 변경하면, Lock 없이(Non-Locking) 데이터를 읽어오기 때문에 서비스 중단 없이 안전하게 복사가 가능하다.
- 데이터 복사
INSERT INTO NEW_CQ_SHORT_INFO
SELECT * FROM CQ_SHORT_INFO
WHERE <보존 조건>;
- 교체 직전 점검
SHOW PROCESSLIST; -- 장기 SELECT 존재 여부 확인 (Metadata Lock 방지)
- RENAME → DROP
효과
- Undo Log 0
- 단편화 제거
- 다운타임은 RENAME 순간뿐
🅑 pt-archiver — 운영 자동화 최종 병기(Percona Toolkit)
pt-archiver \
--source DSN=... \
--where "create_date < '2025-01-01'" \
--limit 1000 \
--commit-each \
--sleep 1 \
--purge \
--primary-key-only \
--check-slave-lag DSN=...
관련 글 :
6️⃣ 고급 최적화 — PK Walking Iterator
DELETE FROM CQ_SHORT_INFO
WHERE id >= v_current_id
AND id < v_current_id + p_batch;
7️⃣ 재발 방지 (Prevention)
- 단일 대량 DELETE 금지
- 부분 삭제 → Batch / pt-archiver
- 대량 삭제 → Copy & Swap
- Foreign Key / Isolation Level / Metadata Lock 사전 점검
8️⃣ 한 줄 요약
대량 DELETE는 DB 장애의 지름길이다.
조금 지울 땐 배치로, 많이 지울 땐 새로 만들어라.
📎 Appendix — Stored Procedure 기반 안전한 Batch Delete 구현
부분 삭제 상황에서 가장 안정적인 배치 처리 방식이다.
DELIMITER $$
CREATE PROCEDURE purge_cq_short_info(IN p_batch INT, IN p_sleep_ms INT)
BEGIN
DECLARE v_rows INT DEFAULT 1;
WHILE v_rows > 0 DO
START TRANSACTION;
DELETE FROM CQ_SHORT_INFO
WHERE id IS NOT NULL
ORDER BY id
LIMIT p_batch;
SET v_rows = ROW_COUNT();
COMMIT;
IF v_rows > 0 AND p_sleep_ms > 0 THEN
DO SLEEP(p_sleep_ms / 1000);
END IF;
END WHILE;
END$$
DELIMITER ;
CALL purge_cq_short_info(10000, 50);
🛠 마지막 수정일: 2025.12.30
💡 도움이 필요하신가요?
Zabbix, Kubernetes, 그리고 다양한 오픈소스 인프라 환경에 대한 구축, 운영, 최적화, 장애 분석,
광고 및 협업 제안이 필요하다면 언제든 편하게 연락 주세요.
📧 Contact: jikimy75@gmail.com
💼 Service: 구축 대행 | 성능 튜닝 | 장애 분석 컨설팅
📖 E-BooK [PDF] 전자책 (Gumroad):
Zabbix 엔터프라이즈 최적화 핸드북
블로그에서 다룬 Zabbix 관련 글들을 기반으로 실무 중심의 지침서로 재구성했습니다.
운영 환경에서 바로 적용할 수 있는 최적화·트러블슈팅 노하우까지 모두 포함되어 있습니다.
💡 Need Professional Support?
If you need deployment, optimization, or troubleshooting support for Zabbix, Kubernetes,
or any other open-source infrastructure in your production environment, or if you are interested in
sponsorships, ads, or technical collaboration, feel free to contact me anytime.
📧 Email: jikimy75@gmail.com
💼 Services: Deployment Support | Performance Tuning | Incident Analysis Consulting
📖 PDF eBook (Gumroad):
Zabbix Enterprise Optimization Handbook
A single, production-ready PDF that compiles my in-depth Zabbix and Kubernetes monitoring guides.