교착 상태(Deadlock)의 원인 중 하나인 "Lock 경합"의 핵심 원리와 관련이 있습니다. 특히 rowlock과 tablelock의 차이를 이해하면 왜 락을 오래 잡고 있으면 위험한지 명확히 알 수 있습니다.
✅ 1. Row Lock vs Table Lock의 개념 비교
대상 |
1개의 행 (ROW) |
테이블 전체 |
범위 |
선택된 레코드 |
해당 테이블에 있는 모든 행 |
동시성 |
✅ 매우 높음 (다른 행 접근 가능) |
❌ 낮음 (전체 잠금) |
사용 시점 |
WHERE 조건이 정확하고 인덱스 존재 |
조건이 넓거나, 인덱스 없거나, 대량 DML 시 자동 확장 |
성능 |
가장 좋음 |
느림, 병렬성 저하 |
🔍 예시
-- Row Lock 발생
UPDATE TB_ITEM SET QTY = QTY - 1 WHERE ITEM_ID = 123;
- ITEM_ID에 인덱스가 있다면 해당 ROW 하나만 락 걸림 → Row Lock
- 조건 범위가 넓고, ITEM_NAME에 인덱스가 없거나 통계가 부정확 → Page Lock → Table Lock 확장
⚠️ A가 락을 오래 잡고 있고 B가 같은 자원에 접근할 때 문제
시나리오
세션 A세션 B
UPDATE TB_ITEM WHERE ITEM_ID = 123 → Row Lock 획득, 오래 점유 (예: 30초) |
UPDATE TB_ITEM WHERE ITEM_NAME LIKE '전%' → Table Lock 시도 |
계속 실행 중 |
A가 가진 Row Lock 때문에 전체 Table Lock 못 잡음 |
|
💥 교착 상태 또는 대기 발생 |
🔒 Lock Escalation (락 확장) 개념
- SQL Server는 기본적으로 Row Lock → Page Lock → Table Lock으로 자동 확장합니다.
- 기준: 5,000개 이상의 Row Lock이 잡히면 Page/Table Lock으로 확장 가능
확장 트리거설명
많은 행 업데이트 |
수천 개 Row Lock → Page Lock 필요 |
조건 없이 UPDATE, DELETE |
테이블 전체 → 바로 Table Lock |
인덱스 없음 |
WHERE 조건에서 적절한 ROW 대상 식별 불가 → 범위 Lock 발생 |
🧨 교착 상태가 발생하는 원인 요약
상황설명
세션 A가 Row Lock을 오래 보유 |
B가 해당 Row를 포함하는 더 넓은 범위에 락을 걸려함 |
락 확장(에스컬레이션) 시도 |
이미 락 보유 중인 Row가 있어 Table Lock 실패 |
서로 반대 순서로 테이블 접근 |
A: TB_ITEM → TB_LOG, B: TB_LOG → TB_ITEM |
✅ 예방 전략 요약
전략설명
✅ 인덱스 최적화 |
WHERE 조건에 맞는 인덱스 있어야 Row Lock 가능 |
✅ 락 순서 고정 |
트랜잭션마다 테이블 접근 순서 동일하게 유지 |
✅ 트랜잭션 시간 최소화 |
DB 작업 외 로직은 트랜잭션 밖으로 이동 |
✅ read-only 쿼리는 NOLOCK |
예: SELECT ... WITH (NOLOCK) |
✅ 대량 작업은 오프타임 처리 |
밤이나 분산 배치 처리로 충돌 방지 |
💡 보너스: 강제로 Row Lock만 쓰는 방법
SELECT * FROM TB_ITEM WITH (ROWLOCK) WHERE ITEM_ID = 123;
주의: 직접 명시하지 않으면 SQL Server는 상황에 따라 락을 "자동으로 확장"할 수 있습니다.
✅ 결론
질문요약 답변
A가 락을 오래 잡고 있고 B가 접근하면? |
B는 Row Lock or Table Lock을 시도하다 충돌하거나 교착 상태에 빠질 수 있음 |
Row Lock vs Table Lock |
Row Lock은 정확하고 인덱스 있을 때 발생, Table Lock은 조건 넓거나 Row가 많을 때 발생 |
교착 방지하려면? |
락 순서 통일, 인덱스 보장, 트랜잭션 최소화가 핵심 |