我的应用程序经常陷入僵局,因为
pubic Create()
{
open.conn
begintransaction(readcommitted)
try{
using (TransactionScope scope = new TransactionScope(TransactionScopeOption.Required, transactionOptions))
{
select * from table1 with (holdlock)
}
db.savechanges()
scope.complete()
}
catch{
transaction.Rollback()
}
finally{
transaction.Commit()
}
}
问题:
如果我在事务范围中锁定一个表,如果该表有外键引用,该表也将被锁定我在某处读到的是这样的
直到作用域完成为止,表被锁定并且不能被任何其他事务访问
我无法更改表结构,有人可以帮助我解决正在发生的死锁问题吗?
在finally块中使用事务提交是否正确,因为在提交之前我无法访问锁定在范围内的表
我还使用了隔离级别readcommissed并且我还为我正在使用的表添加了索引
在每个屏幕中,我都使用 **holdlock **
锁定正在使用的表格死锁图:
<deadlock>
<victim-list>
<victimProcess id="process22f404204e8"/>
</victim-list>
<process-list>
<process XDES="0x228601b8460" clientapp=".Net SqlClient Data Provider" clientoption1="671088672" clientoption2="128056" currentdb="7" currentdbname="enterprise_119" ecid="0" hostname="VM-APP-PROD" hostpid="10196" id="process22f404204e8" isolationlevel="serializable (4)" kpid="5780" lastattention="1900-01-01T00:00:00.353" lastbatchcompleted="2024-10-14T15:43:15.353" lastbatchstarted="2024-10-14T15:43:15.337" lasttranstarted="2024-10-14T15:43:14.330" lockMode="IX" lockTimeout="4294967295" loginname="sa" logused="0" ownerId="103212644" priority="0" sbid="9" schedulerid="2" spid="122" status="suspended" taskpriority="0" trancount="2" transactionguid="0xabee73fcc3c679498a23411657f35ea5" transactionname="user_transaction" waitresource="OBJECT: 7:1026154751:0 " waittime="5314" xactid="103212644">
<executionStack>
<frame line="1" procname="adhoc" sqlhandle="0x020000003ec22c1d4fd0254218ea54ce4fa18e7771402ac30000000000000000000000000000000000000000" stmtend="4188" stmtstart="1836"> unknown
</frame>
<frame line="1" procname="unknown" sqlhandle="0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"> unknown
</frame>
</executionStack>
<inputbuf>
(@0 int,@1 datetime2(7),@2 nvarchar(max) ,@3 int,@4 int,@5 int,@6 nvarchar(max) ,@7 nvarchar(max) ,@8 nvarchar(max) ,@9 nvarchar(max) ,@10 bit,@11 bit,@12 nvarchar(100),@13 nvarchar(100),@14 datetime2(7),@15 datetime2(7),@16 nvarchar(100),@17 nvarchar(100),@18 int,@19 nvarchar(max) ,@20 datetime2(7),@21 nvarchar(1000),@22 nvarchar(1000),@23 nvarchar(1000),@24 nvarchar(1000),@25 nvarchar(1000),@26 nvarchar(1000),@27 nvarchar(1000),@28 nvarchar(1000),@29 nvarchar(1000),@30 nvarchar(1000),@31 nvarchar(200),@32 int,@33 int,@34 int,@35 nvarchar(max) ,@36 nvarchar(max) ,@37 nvarchar(max) ,@38 datetime2(7),@39 nvarchar(max) ,@40 nvarchar(max) ,@41 int,@42 nvarchar(250),@43 int,@44 decimal(18,2),@45 decimal(18,2),@46 decimal(18,2),@47 decimal(18,2),@48 int,@49 int,@50 nvarchar(250),@51 datetime2(7),@52 int,@53 decimal(18,6),@54 decimal(18,6),@55 decimal(18,6),@56 decimal(18,6),@57 decimal(18,6),@58 decimal(18,6))
insert [dbo].[production_hdr]([acc_id], [entry_date], [acc_name], [trans_sno], [transtype_id], [transsubt
</inputbuf>
</process>
<process XDES="0x22e4a48c460" clientapp=".Net SqlClient Data Provider" clientoption1="671088672" clientoption2="128056" currentdb="7" currentdbname="enterprise_119" ecid="0" hostname="VM-APP-PROD" hostpid="10196" id="process22e51f16ca8" isolationlevel="serializable (4)" kpid="8072" lastattention="1900-01-01T00:00:00.540" lastbatchcompleted="2024-10-14T15:43:16.540" lastbatchstarted="2024-10-14T15:43:16.540" lasttranstarted="2024-10-14T15:43:13.560" lockMode="IX" lockTimeout="4294967295" loginname="sa" logused="0" ownerId="103211768" priority="0" sbid="9" schedulerid="1" spid="90" status="suspended" taskpriority="0" trancount="2" transactionguid="0x54396b46581b914a84e863da9cd82a59" transactionname="user_transaction" waitresource="OBJECT: 7:1026154751:0 " waittime="4123" xactid="103211768">
<executionStack>
<frame line="1" procname="adhoc" sqlhandle="0x020000003ec22c1d4fd0254218ea54ce4fa18e7771402ac30000000000000000000000000000000000000000" stmtend="4188" stmtstart="1836"> unknown
</frame>
<frame line="1" procname="unknown" sqlhandle="0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"> unknown
</frame>
</executionStack>
<inputbuf>
(@0 int,@1 datetime2(7),@2 nvarchar(max) ,@3 int,@4 int,@5 int,@6 nvarchar(max) ,@7 nvarchar(max) ,@8 nvarchar(max) ,@9 nvarchar(max) ,@10 bit,@11 bit,@12 nvarchar(100),@13 nvarchar(100),@14 datetime2(7),@15 datetime2(7),@16 nvarchar(100),@17 nvarchar(100),@18 int,@19 nvarchar(max) ,@20 datetime2(7),@21 nvarchar(1000),@22 nvarchar(1000),@23 nvarchar(1000),@24 nvarchar(1000),@25 nvarchar(1000),@26 nvarchar(1000),@27 nvarchar(1000),@28 nvarchar(1000),@29 nvarchar(1000),@30 nvarchar(1000),@31 nvarchar(200),@32 int,@33 int,@34 int,@35 nvarchar(max) ,@36 nvarchar(max) ,@37 nvarchar(max) ,@38 datetime2(7),@39 nvarchar(max) ,@40 nvarchar(max) ,@41 int,@42 nvarchar(250),@43 int,@44 decimal(18,2),@45 decimal(18,2),@46 decimal(18,2),@47 decimal(18,2),@48 int,@49 int,@50 nvarchar(250),@51 datetime2(7),@52 int,@53 decimal(18,6),@54 decimal(18,6),@55 decimal(18,6),@56 decimal(18,6),@57 decimal(18,6),@58 decimal(18,6))
insert [dbo].[production_hdr]([acc_id], [entry_date], [acc_name], [trans_sno], [transtype_id], [transsubt]
</inputbuf>
</process>
</process-list>
<resource-list>
<objectlock associatedObjectId="1026154751" dbid="7" id="lock22bf1985200" lockPartition="0" mode="S" objectname="enterprise_119.dbo.production_hdr" objid="1026154751" subresource="FULL">
<owner-list>
<owner id="process22e51f16ca8" mode="S"/>
<owner id="process22e51f16ca8" mode="IX" requestType="convert"/>
</owner-list>
<waiter-list>
<waiter id="process22f404204e8" mode="IX" requestType="convert"/>
</waiter-list>
</objectlock>
<objectlock associatedObjectId="1026154751" dbid="7" id="lock22bf1985200" lockPartition="0" mode="S" objectname="enterprise_119.dbo.production_hdr" objid="1026154751" subresource="FULL">
<owner-list>
<owner id="process22f404204e8" mode="S"/>
<owner id="process22f404204e8" mode="IX" requestType="convert"/>
</owner-list>
<waiter-list>
<waiter id="process22e51f16ca8" mode="IX" requestType="convert"/>
</waiter-list>
</objectlock>
</resource-list>
</deadlock>
结论:有人可以就如何在我的场景中防止死锁提出一些建议吗?
您使用的隔离级别(已提交读)是任何选择的默认值,您可以防止脏读,只读取已提交的值,因此不需要它。
我不确定为什么你要使用“holdlock”进行选择,并且最重要的是相当于可串行化隔离级别这就是导致死锁的原因,因为它使得没有其他事务可以修改当前事务已读取的数据,直到当前事务完成。 在当前事务完成之前,其他事务无法插入键值落在当前事务中任何语句读取的键范围内的新行。
而且我也没有看到需要进行简单选择的事务
将选择更改为:
select * from table1 with (nolock)
它将摆脱你的僵局