SQL Server를 선택하여 차단을 유발합니다
-
06-07-2019 - |
문제
우리는 엄청난 선택 명령문이있는 SQL Server 2005 데이터베이스 (행 버전 없음)를 사용하고 있으며, 실행에서 다른 문장을 차단하는 것을보고 있습니다 ( sp_who2
). 선택한 진술이 차단을 일으킬 수 있다는 것을 몰랐습니다. 이것을 완화하기 위해 할 수있는 일이 있습니까?
해결책
CAN 블록 업데이트를 선택합니다. 적절하게 설계된 데이터 모델과 쿼리는 최소한의 차단 만 유발하며 문제가되지 않습니다. Nolock 힌트가있는 '평소'는 거의 항상 잘못된 대답입니다. 적절한 대답은 쿼리를 조정하여 거대한 테이블을 스캔하지 않도록하는 것입니다.
쿼리가 조율되지 않으면 먼저 고려해야합니다. 스냅 샷 격리 레벨, 두 번째로 사용을 고려해야합니다 데이터베이스 스냅 샷 마지막 옵션은 더러운 읽기 여야합니다 (그리고 변경하는 것이 좋습니다. 격리 수준 놀락 힌트를 사용하는 대신). 이름에서 명확하게 말하면 Dirty Read는 일관성이없는 데이터를 반환합니다 (예 : 총 시트는 불균형 일 수 있음).
다른 팁
에서 선적 서류 비치:
Shared (S)
잠금 장치는 동시 트랜잭션을 읽을 수 있도록합니다(SELECT)
비관적 동시성 통제하에있는 자원. 자세한 내용은 참조하십시오Types of Concurrency Control
. 다른 트랜잭션은 데이터를 수정할 수 없습니다shared (S)
자원에 자물쇠가 있습니다.Shared (S)
트랜잭션 격리 레벨이 반복 가능한 읽기 또는 더 높은 것으로 설정되거나 잠금 힌트가 사용되지 않는 한 자원의 잠금은 읽기 작업이 완료 되 자마자 릴리스됩니다.shared (S)
거래 기간 동안 잠금.
ㅏ shared lock
다른 공유 잠금 장치 또는 업데이트 잠금 장치와 호환되지만 Exlibor Lock은 아닙니다.
그것은 당신을 의미합니다 SELECT
쿼리가 차단됩니다 UPDATE
그리고 INSERT
쿼리 및 그 반대도 마찬가지입니다.
ㅏ SELECT
쿼리는 테이블에서 값 블록을 읽을 때 임시 공유 잠금 장치를 배치하고 읽을 때 제거합니다.
잠금이 존재하는 경우 잠긴 영역의 데이터로 아무것도 할 수 없습니다.
둘 SELECT
쿼리는 서로를 차단하지 않습니다 (그렇지 않은 한 SELECT FOR UPDATE
)
당신은 활성화 할 수 있습니다 SNAPSHOT
데이터베이스에서 격리 레벨을 사용하여 사용하지만 방지하지는 않습니다. UPDATE
쿼리가 잠겨있는 쿼리 SELECT
쿼리 (귀하의 경우 인 것 같습니다).
그러나 그것은 예방할 것입니다 SELECT
쿼리가 잠겨있는 쿼리 UPDATE
.
또한 주목하십시오 SQL Server
,와 달리 Oracle
, 잠금 관리자를 사용하여 메모리 내 링크 된 목록에 잠금을 유지합니다.
즉, 무거운 하중에서 링크 된 목록 자체가 트랜잭션 스레드에 의해 잠겨 있어야하기 때문에 잠금을 배치하고 제거하는 것만으로도 속도가 느려질 수 있습니다.
더러운 읽기를 수행하려면 다음 중 하나를 수행 할 수 있습니다.
using (new TransactionScope(TransactionScopeOption.Required,
new TransactionOptions {
IsolationLevel = System.Transactions.IsolationLevel.ReadUncommitted }))
{
//Your code here
}
또는
SelectCommand = "SELECT * FROM Table1 WITH (NOLOCK) INNER JOIN Table2 WITH (NOLOCK) ..."
더러운 읽기를 원하는 모든 테이블 후에 (Nolock)와 함께 써야한다는 것을 기억하십시오.
당신은 설정할 수 있습니다 거래 수준 커밋되지 않은 것을 읽습니다
교착 상태를 얻을 수도 있습니다.
"하나의 테이블 만 포함 된 교착 상태"http://sqlblog.com/blogs/alexander_kuznetsov/archive/2009/01/01/reproducing-deadlocks-involving-on-on-table.aspx
또는 잘못된 결과 :
"읽기에 따라 선택하고 반복 가능한 읽기에서 선택하면 잘못된 결과를 반환 할 수 있습니다."
당신이 사용할 수있는 WITH(READPAST)
테이블 힌트. 그것은 그것과 다릅니다 WITH(NOLOCK)
. 트랜잭션이 시작되기 전에 데이터를 얻을 수 있으며 아무도 차단하지 않습니다. 거래가 시작되기 전에 성명서를 실행했다고 상상해보십시오.
SELECT * FROM table1 WITH (READPAST)