The reason for blocking the entire table was that ALLOW_ROW_LOCKS = OFF and ALLOW_PAGE_LOCKS = OFF were disabled on our index. Hope this helps someone.
Why does MS SQL use exclusive locks on the entire table to update one record?
We have problems with deadlocks, judging by the logs, two requests simultaneously want to get exclusive access to the table. However, both queries change one record in the table. The error occurs at high loads. There was a lack of RAM. In this case, we use the READ COMMITTED SNAPSHOT isolation level. I understand that this isolation level is very dependent on temporary tables and if there is a lack of memory, then it will not lead to anything good. But I'm trying to explain why an exclusive table lock occurs, what is the reason?
Error log:
<deadlock>
<victim-list>
<victimProcess id="process15869037088" />
</victim-list>
<process-list>
<process id="process15869037088" taskpriority="0" logused="0" waitresource="OBJECT: 8:398376934:0 " waittime="3982" ownerId="1339581101" transactionname="user_transaction" lasttranstarted="2020-12-29T10:11:51.320" XDES="0x158623448e0" lockMode="S" schedulerid="4" kpid="10944" status="suspended" spid="77" sbid="0" ecid="0" priority="0" trancount="2" lastbatchstarted="2020-12-29T10:11:51.310" lastbatchcompleted="2020-12-29T10:11:51.303" lastattention="1900-01-01T00:00:00.303" clientapp=".Net SqlClient Data Provider" hostname="KITZBUEHEL" hostpid="12192" loginname="eseddadmin" isolationlevel="serializable (4)" xactid="1339581101" currentdb="8" currentdbname="SEDD3_KIO" lockTimeout="4294967295" clientoption1="671090784" clientoption2="128056">
<executionStack>
<frame procname="SEDD3_KIO.dbo.spCloseApprovalRoutes" line="29" stmtstart="1286" stmtend="1796" sqlhandle="0x03000800970e9d2c3c2e3e019ba8000001000000000000000000000000000000000000000000000000000000">
UPDATE S SET
State = 4,
CompleteDate = @Dt
FROM WF4_Stations S inner join WF4_Routes R on RouteID = R.ID AND S.State IN (0,1,2,5) AND S.PRUZ <> 1
AND DocUID = @docUID AND R.State NOT IN(3,4,6) AND R.PRUZ <> 1 AND R.Type = </frame>
</executionStack>
<inputbuf>
Proc [Database Id = 8 Object Id = 748490391] </inputbuf>
</process>
<process id="process1585ad4c8c8" taskpriority="0" logused="10036" waitresource="OBJECT: 8:398376934:0 " waittime="3986" ownerId="1339581866" transactionname="user_transaction" lasttranstarted="2020-12-29T10:11:51.537" XDES="0x15862341520" lockMode="X" schedulerid="3" kpid="8148" status="suspended" spid="68" sbid="0" ecid="0" priority="0" trancount="2" lastbatchstarted="2020-12-29T10:11:51.537" lastbatchcompleted="2020-12-29T10:11:51.533" lastattention="1900-01-01T00:00:00.533" clientapp=".Net SqlClient Data Provider" hostname="KITZBUEHEL" hostpid="12192" loginname="eseddadmin" isolationlevel="read committed (2)" xactid="1339581866" currentdb="8" currentdbname="SEDD3_KIO" lockTimeout="4294967295" clientoption1="673187936" clientoption2="128056">
<executionStack>
<frame procname="SEDD3_KIO.dbo.spSaveApprovalSigning" line="122" stmtstart="8704" stmtend="9600" sqlhandle="0x030008000880664e1acff10087ac000001000000000000000000000000000000000000000000000000000000">
update WF4_Routes set
State = case when @Dt >= stat.ControlDate then 4 else 3 end,
CompleteDate = @Dt,
UserUID = @OperatorUID,
ModifyDate = @Dt
from WF4_Routes R
inner join WF4_Stages stages
on R.ID = @RouteID
and stages.RouteID = R.ID
and stages.StageType = 7
and stages.PRUZ <> 1
inner join WF4_Stations stat
on stat.ApprovalStageID = stages.ID
and stat.PRUZ <> </frame>
</executionStack>
<inputbuf>
Proc [Database Id = 8 Object Id = 1315340296] </inputbuf>
</process>
</process-list>
<resource-list>
<objectlock lockPartition="0" objid="398376934" subresource="FULL" dbid="8" objectname="SEDD3_KIO.dbo.WF4_Routes" id="lock151c8d7d800" mode="IX" associatedObjectId="398376934">
<owner-list>
<owner id="process1585ad4c8c8" mode="IX" />
<owner id="process1585ad4c8c8" mode="X" requestType="convert" />
</owner-list>
<waiter-list>
<waiter id="process15869037088" mode="S" requestType="convert" />
</waiter-list>
</objectlock>
<objectlock lockPartition="0" objid="398376934" subresource="FULL" dbid="8" objectname="SEDD3_KIO.dbo.WF4_Routes" id="lock151c8d7d800" mode="IX" associatedObjectId="398376934">
<owner-list>
<owner id="process15869037088" mode="IS" />
<owner id="process15869037088" mode="S" requestType="convert" />
</owner-list>
<waiter-list>
<waiter id="process1585ad4c8c8" mode="X" requestType="convert" />
</waiter-list>
</objectlock>
</resource-list>
</deadlock>
1 additional answer
Sort by: Most helpful
-
JoyDutt 821 Reputation points
2020-12-29T11:39:54+00:00 Hi @Михаил
The way to do it in SQL Server is to set an isolation level on the transaction that contains the statements that you want to execute. See this REF page (at bottom of this answer) but the general structure would look something like:SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
BEGIN TRANSACTION;
select * from ...
update ...
COMMIT TRANSACTION;
SERIALIZABLE is the highest isolation level.