반응형
MySQL에서 DML(INSERT, UPDATE, DELETE)을 사용할 때 잠금(LOCK) 개념은 단순한 동시성 제어 그 이상이다. 실무에서는 자주 발생하는 데드락(Deadlock)이나 락 경합 문제를 예방하고 해결하는 것이 성능 유지와 데이터 무결성 보장에 핵심이다.

🔧 MySQL의 락 종류
1. 테이블 락 (Table Lock)
- MyISAM 등에서 주로 사용
- 테이블 전체를 잠금
- 동시에 하나의 세션만 DML 가능
LOCK TABLES users WRITE;
-- users 테이블에 쓰기 락이 걸림
2. 행 레벨 락(Row-Level Lock) - InnoDB
- 레코드 단위로 락 적용
- 동시에 여러 세션에서 병렬 DML 가능
- InnoDB 기본 동작 방식
UPDATE users SET name = 'Mike' WHERE id = 1;
-- id=1인 레코드만 잠금
반응형
⚠️ DML 수행 시 자동으로 발생하는 락
| DML 명령어 | 기본 락 동작 (InnoDB 기준) |
| SELECT ... FOR UPDATE | 공유/배타적 락 |
| INSERT | 삽입되는 레코드에 락 |
| UPDATE | 해당 행에 배타적(X) 락 |
| DELETE | 삭제되는 행에 배타적(X) 락 |
참고: InnoDB는 MVCC 기반으로 SELECT 자체는 락을 걸지 않는다.
🧱 락 충돌(Lock Conflict) 상황
예시 1: 동일 행 UPDATE 충돌
-- 세션 1
START TRANSACTION;
UPDATE users SET age = age + 1 WHERE id = 100;
-- 세션 2
START TRANSACTION;
UPDATE users SET name = 'Lee' WHERE id = 100;
→ 세션 2는 세션 1의 락이 해제될 때까지 대기하거나, 락 대기 타임아웃이 발생한다.
반응형
⛔ 데드락 발생과 해결
데드락(Deadlock)은 서로의 자원을 기다리는 교착 상태를 말한다.
예시 2: 교차 UPDATE 충돌
-- 세션 A
START TRANSACTION;
UPDATE users SET age = 30 WHERE id = 1;
-- 세션 B
START TRANSACTION;
UPDATE users SET age = 25 WHERE id = 2;
-- 세션 A
UPDATE users SET age = 30 WHERE id = 2; -- 세션 B가 잠금 중
-- 세션 B
UPDATE users SET age = 25 WHERE id = 1; -- 세션 A가 잠금 중
→ 이 경우 MySQL은 둘 중 하나의 트랜잭션을 강제 종료(Rollback) 처리한다.
해결 방법
- 한 방향으로만 쿼리 실행 순서를 통일 (id 순 정렬 등)
- 가능한 한 짧은 트랜잭션 단위로 처리
- 꼭 필요한 경우에만 명시적 락 사용
🔍 트랜잭션 격리 수준과 락 관계
| 격리 수준 | 설명 | SELECT 락 사용 여부 |
| READ UNCOMMITTED | 변경 중인 데이터도 읽음 | X |
| READ COMMITTED | 커밋된 데이터만 읽음 | X |
| REPEATABLE READ (기본값) | 트랜잭션 내 같은 결과 보장 | MVCC로 처리 |
| SERIALIZABLE | 완전한 직렬화 보장 | SELECT 시에도 락 발생 |
명시적으로 락 걸기
SELECT * FROM users WHERE id = 1 FOR UPDATE;
→ 트랜잭션 내에서 해당 행을 다른 세션이 수정하지 못하게 보호
반응형
🧰 실무에서 사용하는 쿼리 패턴
1. 동시성 제어가 필요한 재고 처리
START TRANSACTION;
SELECT stock FROM products WHERE id = 10 FOR UPDATE;
-- 재고 확인 후 처리
UPDATE products SET stock = stock - 1 WHERE id = 10;
COMMIT;
2. Deadlock 회피를 위한 정렬된 업데이트
-- 항상 id 순서대로 처리
UPDATE users SET point = point + 10 WHERE id IN (101, 102) ORDER BY id;
🧩 LOCK 관련 설정 및 모니터링
- 락 대기 시간 확인: SHOW ENGINE INNODB STATUS;
- 락 대기 시간 조정:
SET innodb_lock_wait_timeout = 5;
- 현재 락 확인:
SELECT * FROM performance_schema.data_locks;
📘 공식문서 참고
반응형
'DB' 카테고리의 다른 글
| [MySQL] EXPLAIN으로 인덱스 성능 튜닝하는 법 (실행계획 완전 분석) (0) | 2025.07.03 |
|---|---|
| [MySQL] 인덱스 설계 가이드: 실무에서 실패하지 않는 인덱스 전략 🛠️ (0) | 2025.07.03 |
| [MySQL] 인덱스 종류 완전정복 (BTREE, HASH, FULLTEXT, SPATIAL)🧩 (0) | 2025.07.03 |
| [MySQL] 인덱스란? 개념과 필요한 이유 완벽 정리 🧠 (0) | 2025.07.03 |
| [MySQL] DML과 트랜잭션 오토커밋 제어 완벽 정리 ⚙️ (0) | 2025.07.03 |
| [MySQL] DML과 FOREIGN KEY 제약조건 관리 완전 정복 🔗 (2) | 2025.07.03 |
| [MySQL] 트리거로 DELETE 감지: BEFORE / AFTER 완벽 가이드 🗑️ (2) | 2025.07.03 |
| [MySQL] 트리거로 UPDATE 감지: BEFORE / AFTER 활용법 완전 정복 🛠️ (0) | 2025.07.03 |