이번에 작업한 개발 내용 중, 데이터 컨버전이 필요한 부분이 있었는데, 해당 내용 실행 시, 테이블 락이 걸리면서 관련 테이블에 데이터를 쓸 수 없는(Write) 상황이 발생했다.
테이블 락이란?
트랜잭션이나 명령이 하나의 테이블 전체에 대해 잠금을 거는 행위
락이 걸린 동안에는 다른 트랜잭션이 해당 테이블에 대해 읽거나 쓸 수 없다.
구분InnoDBMyISAM
| 기본 락 | Row-level Lock (행 락) | Table-level Lock (테이블 락) |
| 락 충돌 가능성 | 낮음 | 높음 |
| 동시성 | 높음 | 낮음 |
| 특징 | 트랜잭션 지원 | 트랜잭션 미지원 |
우리는 InnoDB를 사용하기 때문에, InnoDB에서 테이블 락이 발생하는 대표적인 사례를 나열해보자.
InnoDB에서 테이블 락이 걸리는 대표적 사례
- Foreign Key 제약 조건 충돌
- 부모 테이블을 참조하고 있는 자식 테이블에 INSERT 중이라면, 부모 테이블에도 락이 걸릴 수 있다.
- 대량의 데이터 삽입 (Bulk Insert)
- INSERT INTO ... SELECT 또는 대량 INSERT 시, 락 획득 시간 지연 → metadata lock 또는 table lock 발생
→ 여기서 SELECT 에서 참조 된 테이블(Source table)에도 읽기 락이 걸린다.
테이블 락 방지 및 해결 방법
해결 방법설명
| 트랜잭션 짧게 유지 | BEGIN ~ COMMIT 사이 시간 최소화 |
| 대량 작업을 Chunk로 나누기 | 1000건씩 나눠서 INSERT |
| AUTO_INCREMENT 병렬 사용 피하기 | MySQL 8.0 이상 권장 |
| FOREIGN KEY 최소화 or 명확히 설계 | 불필요한 FK는 제거 또는 연관 INSERT 분리 |
| SELECT 시 LOCK IN SHARE MODE, FOR UPDATE 주의 | 트랜잭션 내에서 신중히 사용 |
| 명시적 테이블 락 사용 자제 | 특별한 이유 없으면 사용 금지 |
이번에 발생한 상황은, 대량의 데이터를 Bulk insert하면서 생긴 상황인 것 같았다.
그래서 개별 insert로 방식을 바꾸어 진행하기로 결정했다.
아마 FK는 효율성때문에 잘 사용하지 않는 걸로 알아서, 관련 문제는 잘 안 생길 것 같은데, Bulk insert의 경우는 대량의 데이터로 실행할 일이 있을 때, 해당 테이블이 락이 걸려도 괜찮은지에 대해서 생각해 볼 필요가 있을 것 같다.
'DB' 카테고리의 다른 글
| Percona MySQL 감사로그 설정 (0) | 2025.12.28 |
|---|---|
| Percona MySQL TDE 설정 (0) | 2025.12.28 |
| [DB] 풀 인덱스 스캔, 인덱스 전용 스캔(커버링 인덱스) (0) | 2025.12.28 |
| [MySQL] 테이블 파티셔닝 (0) | 2025.04.14 |