SQL Server에서 "Transaction (Process ID 66) was deadlocked on lock resources with another process and has been chosen as the deadlock victim. Rerun the transaction." 오류는 두 개 이상의 트랜잭션이 동일한 자원(예: 행, 테이블)에 대한 잠금을 획득하려고 할 때 발생하는 상호 잠금, 즉 데드락(deadlock) 상태를 나타냅니다.
데드락은 트랜잭션들이 서로를 무한히 기다리는 상태를 만듭니다. 예를 들어, 트랜잭션 A가 자원 1에 대한 잠금을 가지고 있고 자원 2에 대한 잠금을 기다리고 있으며, 동시에 트랜잭션 B는 자원 2에 대한 잠금을 가지고 있고 자원 1에 대한 잠금을 기다리고 있는 상황입니다. 둘 다 다음 단계로 진행하지 못하고 상대방의 잠금이 해제되기만을 기다리게 됩니다.
SQL Server는 이러한 데드락 상황을 감지하고 해결하기 위해 데드락 탐지기를 사용합니다. 이 탐지기는 데드락이 발생하면 한 트랜잭션을 희생시켜(데드락 피해자로 선택) 데드락을 해결하고 다른 트랜잭션이 계속 진행할 수 있게 합니다. 희생된 트랜잭션은 롤백되고 오류 메시지가 반환됩니다.
데드락 문제를 해결하기 위한 몇 가지 일반적인 접근 방법은 다음과 같습니다:
-
최소화된 잠금 사용: 가능한 트랜잭션 동안 잠금을 최소한으로 유지하고, 필요한 최소한의 데이터만을 잠그도록 쿼리를 최적화합니다.
-
일관된 순서로 자원 접근: 모든 트랜잭션이 자원을 동일한 순서로 요청하도록 쿼리를 재구성함으로써 데드락 가능성을 줄일 수 있습니다.
-
분리 수준 조정: 트랜잭션의 분리 수준(Isolation Level)을 조정하여 더 적은 잠금을 사용하도록 할 수 있습니다. 하지만 이는 동시성 문제를 일으킬 수 있으므로 주의가 필요합니다.
-
타임아웃 사용: 타임아웃을 짧게 설정하여 오랜 시간 동안 자원을 잠그고 있는 트랜잭션을 방지합니다.
-
힌트 사용: SQL 쿼리에 (NOLOCK)과 같은 힌트를 사용하여 잠금을 회피할 수 있지만, 이는 읽기 일관성 문제를 야기할 수 있습니다.
-
트랜잭션 재시도 로직 구현: 애플리케이션 측에서 데드락 오류를 포착하고 자동으로 트랜잭션을 재시도할 수 있는 로직을 구현합니다.
데드락 문제를 분석하고 해결하기 위해 SQL Server는 데드락 그래프를 포함한 세부 정보를 제공하는 트레이스 플래그나 SQL Server Profiler, Extended Events 등의 도구를 제공합니다. 이러한 도구를 사용하여 데드락의 원인을 파악하고 적절한 조치를 취할 수 있습니다.