간단한 문제 - SQL Server 테이블에 300k 개의 작업이 있으며 여러 프로세스가 하나씩 선택하여 처리하고 결과를 저장합니다.XLOCK ROWLOCK을 사용하여 선택시 TSQL 데드락
그리고 때때로 수확과 저장에 교착 상태가 발생합니다.
두 프로세스가 동일한 작업을 선택하지 않도록해야합니다. 그래서 XLOCK
을 사용하고 있으며, 작업이 완료되면 상태가 1- Created에서 Started로 변경되며 이후에는 3-Completed로 처리됩니다.
또한 내 작업 (tblTasksSets
)는 일대일 tblGeneralSets
에 (문의 바랍니다) 참조) 및 tblGeneralSets
대일 tblContainers
에 참조됩니다. 완료로 작업을 표시하는
DECLARE @SetIds AS TABLE(Id INT)
-- Updating status
;WITH innerTable AS
(
SELECT TOP 1 taskSets.*
FROM tblTasksSets taskSets WITH (XLOCK ROWLOCK)
INNER JOIN tblGeneralSets generalSets WITH(XLOCK ROWLOCK) ON generalSets.TaskSetId = taskSets.Id
WHERE generalSets.ContainerId = @ContainerId
AND taskSets.ParameterSetStatusId = 1 --CREATED
)
UPDATE innerTable
SET ParameterSetStatusId = 2 -- STARTED
OUTPUT INSERTED.Id INTO @SetIds
-- Here are some unrelated updates on log history tables
-- And returning result
SELECT
taskSets.*, containers.*
FROM
tblTasksSets taskSets
INNER JOIN
tblGeneralSets generalSets ON generalSets.TaskSetId = taskSets.Id
INNER JOIN
tblContainers containers ON containers.Id = generalSets.ContainerId
WHERE
taskSets.Id = (SELECT TOP 1 Id FROM @SetIds)
와 두 번째 :
UPDATE tblTasksSets
SET
....
WHERE Id = @Id
어떤 아이디어가 왜 교착 상태를 받고 있어요
그래서 나는 업데이트 집어 작업을 선택하려면이 개 절차의 하나가? 한 프로세스가 다른 프로세스가 업데이트를 완료 할 때까지 기다리면됩니다.
System.Data.SqlClient.SqlException (0x80131904) 트랜잭션 (프로세스 ID 53) 잠금 리소스를 다른 프로세스에 교착시키고, 교착 상태로 선택되었다. 트랜잭션을 재실행하십시오.
테스트 당시이 db에 대해 실행 된 다른 쿼리는 없었습니다. 리소스에 대한 액세스를 직렬화하기 위해 무력 방법이 어쩌면
sp_lock shows something like this
그 동안 'sp_lock'을 실행하면 하나의 연결 만 차단하려는 경우 많은 행을 차단한다는 것을 알 수 있습니다. 이는 적절한 색인의 조인 및/또는 부족 때문일 것입니다. 그렇지 않은 경우에도 다른 연결은 현재 잠긴 행이'where'를 만족하지 못하도록 기다려야하므로 동시성이 0이됩니다. – GSerg
아마 당신은'update top (1) ... from ... (rowlock, holdlock, readpast) where ...'를 원할 것입니다. [readpast 힌트] (https://docs.microsoft.com/en-us/sql/t-sql/queries/hints-transact-sql-table). – GSerg
교착 상태 그래프를 게시 할 수 있습니까? http://sqlmag.com/database-performance-tuning/gathering-deadlock-information-deadlock-graph – Shaulinator