【问题标题】:Transaction Isolation Level of Serializable not working for me可序列化的事务隔离级别对我不起作用
【发布时间】:2011-01-31 01:38:29
【问题描述】:

我有一个网站,商店的所有分支机构都在使用它,它的作用是将客户购买记录到一个名为 myTransactions 的表中。myTransactions 表有一个名为 SerialNumber 的列。对于每次购买,我都会在交易表中创建一条记录并为其分配一个序列号。执行此操作的存储过程调用 UDF 函数以在插入记录之前获取新的序列号。如下所示:


Create Procedure mytransaction_Insert
as begin
insert into myTransactions(column1,column2,column3,...SerialNumber) 
values( Value1 ,Value2,Value3,...., getTransactionNSerialNumber())  
end

Create function getTransactionNSerialNumber
as
begin
RETURN isnull(SELECT TOP (1) SerialNumber FROM myTransactions READUNCOMMITTED
ORDER BY SerialNumber DESC),0) + 1
end

该网站被不同商店的众多用户同时使用,并且创建了许多重复的序列号(相同的序列号)。所以我在事务中添加了一个 ReadCommitted 级别的 Sql 事务,我仍然得到重复的事务号。我将其更改为 SERIALIZABLE 以锁定资源,我不仅得到了重复的事务号(!!HOW !!),而且在相同的存储过程调用之间也出现了零星的死锁。这是我尝试过的:(省略了 try catch 块和回滚)

Create Procedure mytransaction_Insert
as begin
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE
BEGIN TRASNACTION ins
insert into myTransactions(column1,column2,column3,...SerialNumber) 
values( Value1 ,Value2 , Value3, ...., getTransactionNSerialNumber())  
COMMIT TRANSACTION ins
SET TRANSACTION ISOLATION READCOMMITTED
end

我什至将获取序列号的函数直接复制到存储过程而不是 UDF 函数调用中,但仍然得到重复的序列号。所以,存储过程行如何创建类似于 c# lock() {} 块的东西。 顺便说一句,我必须使用相同的模式来实现交易序列号,我不能将序列号更改为任何其他身份字段或其他任何东西。由于某些原因,我需要在数据库中生成序列号,但我不能将 SerialNumber 生成移至应用程序级别。


对不起,我已经在函数中没有 READUNCOMMITTED 的情况下尝试过这个,但我仍然得到重复的序列号。

至于 IDENTITY 列,我应该说这个应用程序将被其他需要不同 SerialNumber 的公司使用,我们不能简单地将其更改为身份。

【问题讨论】:

    标签: sql-server transactions


    【解决方案1】:

    您在 UDF 中有 READUNCOMMITTED。这将导致它忽略其他事务持有的任何独占锁。

    SET TRANSACTION ISOLATION LEVEL SERIALIZABLEapplock不同,它不是数据库中的“临界区”,它只是控制事务中后续语句的锁定行为。

    取出READUNCOMMITTED,它应该会按您的预期开始工作。

    当然,这忽略了您实质上重新实现了IDENTITY 列的事实。如果您的序列号确实是递增的,那么您应该把所有这些都扔掉,并用一个简单的IDENTITY 列替换它。您声称您“不能”,但没有为该声明提供任何理由;在我看来,你几乎可以肯定可以

    【讨论】:

    • 感谢 sp_getapplock 参考。我不知道有这样的东西存在!
    【解决方案2】:

    您缺少的是事务表中的唯一约束(或主键)。如果您认为重复条目会在您尝试提交时退出。

    但我会明确指出,您应该在 SQL 中使用“身份”(如 @Aaronaught 所说)列。这将从您想要的任何位置开始并向前或向后递增。如果您需要您的订单从给定的数字开始,请转发它。但是,如果您需要一个唯一的标识符并且恰好是一个整数值,那么请使用标识。

    【讨论】:

      猜你喜欢
      • 2021-01-14
      • 1970-01-01
      • 1970-01-01
      • 2011-09-30
      • 2021-12-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-07-21
      相关资源
      最近更新 更多