【发布时间】:2017-07-18 19:14:06
【问题描述】:
我在 Visual Studio 中创建了一个可供多个用户访问的 WinForm。 每当用户访问数据时,我想锁定数据,以便其他用户由于某些业务逻辑而无法同时查看相同的数据。
下面是我的c#代码
using (SqlConnection conn = new SqlConnection(connectString))
{
using (SqlCommand cmd=new SqlCommand("get_First_Unscan_Record_withUpdate",conn))
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("@usrName", username_Form);
conn.Open();
record_number = cmd.ExecuteScalar().ToString();
}
}
我的 SQL 过程
CREATE PROCEDURE [dbo].[get_First_QC_Record_withUpdate]
@usrName nvarchar(50)
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
Declare @srno int
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
select top 1 @srno=srno from [KYC].[dbo].[KYC_Index] (XLOCK) where [qc]='N' and [qc_int]='N' and transform_int='Y' and transform_status='Y' order by srno
update KYC_Index set [qc_int]='Y',[qc_int_by]=@usrName,[qc_int_time]=GETDATE(),@srno=KYC_Index.srno where srno = @srno
select @srno
我的用户仍然遇到死锁错误
{“事务(进程 ID 72)在锁资源上与另一个进程死锁,已被选为死锁牺牲品。重新运行事务。”}
我做错了什么?还是我应该改变?请指导。
【问题讨论】:
-
这不是你实现队列的方式。有一个
update top (1)和rowlock, holdlock, readpast,有它output的id,并有一个涵盖您过滤的所有字段的索引。 -
你不会因为 one 东西而陷入僵局 - 你会因为 two 而陷入僵局。你已经有一个
XLOCK(我个人会选择UPDLOCK),所以它不能只是一个试图成为更新锁的读锁。所以:你这里有交易吗?您的代码中没有一个,但可能有一个TransactionScope可以在您的上下文/SPID 中添加其他锁……有吗?有点感觉你可以在一个 SQL 操作中完成所有这些操作,不过……也许通过OUTPUT子句来获取srno?不过,我首先要尝试的是使用UPDLOCK。然后我会尝试重写为单个 SQL 操作。 -
@GSerg 你是在建议这样的事情吗?使用 (UPDLOCK,HOLDLOCK) 从 KYC_Index t1 更新 t1 集 [qc_int]='Y',[qc_int_by]=@usrName,[qc_int_time]=GETDATE(),@srno=t1.srno 其中 t1.srno = (select top 1 t2.srno from KYC_Index t2 where t2.[qc]='N' and t2.[qc_int]='N' and t2.transform_int='Y' and t2.transform_status='Y' order by t2.srno)跨度>
-
不,这仍然是两个伪装成一个查询。
-
@GSerg 我们需要按 SRNO 顺序更新数据。那就是两个查询。您能否在上述情况下为我指明正确的方向。
标签: c# sql-server visual-studio