공공부하자개발 · 영어 학습 노트
SQL
대용량·배치실행 계획·조인·인덱스·파티션·락·대량 처리0/8 완료
  • 01실행 계획 읽기
  • 02조인 방식: Nested Loop, Hash, Sort Merge 와 드라이빙 테이블
  • 03인덱스 튜닝
  • 04통계 정보와 힌트
  • 05파티션: 범위·목록·해시 분할, 파티션 프루닝, 파티션 단위 관리
  • 06대량 INSERT·UPDATE 와 배치 커밋
  • 07락과 데드락
  • 08대용량 삭제·아카이빙
사이트 소개개인정보처리방침연락처
© 2026 공부하자
홈 › 대용량·배치 › 07 / 8

락과 데드락

잠금 대기, 데드락 원인과 예방, 잠금 조회
섹션 6진행 0 / 8
1왜 배우는가2핵심 원리3코드 예제4응용 변형 예제5자주 하는 실수 (Tip)6정리‹ 이전다음 ›

2. 핵심 원리

2.1 행 잠금과 대기

행을 수정(UPDATE·DELETE·INSERT)하면 그 행에 쓰기 잠금이 걸립니다. 잠금은 COMMIT 이나 ROLLBACK 을 할 때까지 유지됩니다. 같은 행을 수정하려는 다른 세션은 잠금이 풀릴 때까지 기다립니다.

잠긴 행 하나 때문에 세션이 멈춘 것처럼 보이는 것이 잠금 대기입니다. 잠금을 쥔 쪽이 커밋하면 기다리던 세션이 바로 이어 갑니다. 그래서 트랜잭션이 길수록 대기가 길어집니다.

읽기와 잠금의 관계는 DB마다 다릅니다.

항목 Oracle · Tibero MySQL InnoDB MSSQL
일반 SELECT 잠금 없음 잠금 없음 기본은 공유 잠금
읽기가 쓰기를 막나 막지 않음 막지 않음 기본 설정에서는 막을 수 있음
쓰기가 읽기를 막나 막지 않음 막지 않음 기본 설정에서는 막을 수 있음

MSSQL 기본 READ COMMITTED 는 읽을 때도 공유 잠금을 잡아서, 커밋하지 않은 쓰기가 있는 행의 읽기가 기다릴 수 있습니다. READ_COMMITTED_SNAPSHOT 옵션을 켜면 이전 값을 읽어 이 대기가 사라집니다. Oracle 은 읽기가 잠금을 걸지 않아 쓰기를 막지 않습니다.

2.2 시간 순서로 보는 잠금 대기

아래는 예제 데이터(account 3행)로 그린 시간 순서 도식이고 실행 결과가 아닙니다. 두 세션 모두 자동 커밋을 끈 트랜잭션 안에 있습니다.

시간 순서 도식(설명용). 세션 B 가 A 의 잠금 때문에 기다리는 경우입니다.

순서 세션 A 세션 B
1 김대표 잔액을 900 으로 UPDATE
2 (COMMIT 하지 않음) 같은 행을 UPDATE, 기다림
3 30 초 뒤 COMMIT
4 대기 해제, UPDATE 진행

B 의 화면은 2번부터 3번까지 멈춰 있습니다. A 가 ROLLBACK 해도 똑같이 풀립니다. 대기 시간 한도는 DB마다 다릅니다.

DB 기본 대기 한도 한도 초과
Oracle · Tibero 무한(NOWAIT·WAIT n 으로 지정) 지정했을 때만 오류
MySQL InnoDB 50 초(innodb_lock_wait_timeout) 오류 1205
MSSQL 무한(LOCK_TIMEOUT 기본 -1) 설정하면 오류 1222

MySQL 은 대기 시간 초과가 1205 이고 데드락이 1213 입니다. MSSQL 은 반대로 데드락이 1205 입니다. 같은 1205 라도 DB 가 다르면 뜻이 다르니 오류 번호를 섞어 쓰지 않도록 주의합니다.

2.3 데드락이란

데드락은 두 트랜잭션이 서로 상대가 잡은 자원을 기다리는 순환입니다. 어느 한쪽이 양보하지 않으면 영원히 끝나지 않습니다. DB 가 이 순환을 감지하면 한쪽을 골라 오류로 끊습니다.

시간 순서 도식(설명용). 이체 방향이 반대인 두 트랜잭션입니다.

순서 세션 A (1 → 3 이체) 세션 B (3 → 1 이체)
1 id 1 UPDATE (1번 행 잠금)
2 id 3 UPDATE (3번 행 잠금)
3 id 3 UPDATE, B 를 기다림
4 id 1 UPDATE, A 를 기다림
5 순환 감지, 한쪽이 오류로 끊김

3번과 4번에서 A 는 B 를, B 는 A 를 기다립니다. 누구도 COMMIT 을 못 하니 저절로 풀리지 않습니다. DB 는 이 순환을 감지해 한쪽(희생 트랜잭션)을 오류로 끊고, 나머지는 계속 진행합니다.

2.4 데드락 오류의 뒤처리

DB마다 희생 트랜잭션에 남는 상태가 다릅니다. 이 차이를 모르면 오류 뒤에 데이터가 반쯤 남습니다.

항목 Oracle · Tibero MySQL InnoDB MSSQL
오류 ORA-00060 1213 1205
롤백 범위 오류 난 문장만 트랜잭션 전체 트랜잭션 전체
트랜잭션 남아 있음 종료됨 종료됨

Oracle 은 오류 난 문장만 롤백하고 트랜잭션은 남습니다. 애플리케이션이 직접 ROLLBACK 해야 앞 문장의 변경과 잠금이 풀립니다. MySQL 과 MSSQL 은 희생 트랜잭션 전체가 롤백되므로 처음부터 다시 실행하면 됩니다.

핵심

데드락 오류는 예외가 아니라 정상 동작입니다. 애플리케이션은 데드락 오류를 잡아 롤백하고 트랜잭션 전체를 몇 번 다시 시도하도록 만듭니다.

2.5 잠금을 어디에 거는가

DB마다 잠금 단위와 범위가 다릅니다. 필요한 행만 잠기는지, 훨씬 넓게 잠기는지가 대기와 데드락 빈도를 좌우합니다.

  • Oracle: 행 잠금은 에스컬레이션하지 않습니다. 잠긴 행이 많아져도 표 잠금으로 커지지 않습니다.
  • MySQL InnoDB: 행 잠금은 인덱스 레코드에 걸립니다. 조건에 쓸 인덱스가 없으면 훑은 행을 모두 잠급니다.
  • MySQL InnoDB: REPEATABLE READ 에서 범위 조건은 갭 잠금·넥스트 키 잠금이 추가되어, 빈 자리에 넣는 INSERT 도 막힐 수 있습니다.
  • MSSQL: 잠금이 약 5,000 개에 이르면 표 잠금으로 에스컬레이션할 수 있습니다.

정리하면 조건에 맞는 인덱스가 없을수록 더 많은 행이 잠깁니다. 잠금이 넓어지면 서로 부딪힐 확률이 커져서 데드락이 늘어납니다.

2.6 예방 원칙

  • 여러 행·표를 갱신할 때는 항상 같은 순서로 잠급니다. 2.3 의 데드락은 순서가 반대라서 생겼습니다.
  • 트랜잭션은 짧게 씁니다. 잠금을 쥐는 시간이 곧 충돌 확률입니다.
  • 조건 컬럼과 외래 키 컬럼에 인덱스를 둡니다. 없으면 더 많은 행이나 표가 잠깁니다.
  • 사용자 입력을 기다리는 동안 트랜잭션을 열어 두지 않습니다.
핵심 원리
  • 2.1 행 잠금과 대기
  • 2.2 시간 순서로 보는 잠금 대기
  • 2.3 데드락이란
  • 2.4 데드락 오류의 뒤처리
  • 2.5 잠금을 어디에 거는가
  • 2.6 예방 원칙
이전 섹션1 왜 배우는가2 / 6다음 섹션3 코드 예제