Serializable的事务隔离级别对我不起作用

1 sql-server transactions

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


Create Procedure mytransaction_Insert
as begin
insert into myTransactions(column1,column2,column3,...SerialNumber) 
values( Value1 ,Value2,Value3,...., getTransactionNSerialNumber())  
end
Run Code Online (Sandbox Code Playgroud)
Create function getTransactionNSerialNumber
as
begin
RETURN isnull(SELECT TOP (1) SerialNumber FROM myTransactions READUNCOMMITTED
ORDER BY SerialNumber DESC),0) + 1
end
Run Code Online (Sandbox Code Playgroud)

该网站正在被不同商店中的许多用户同时使用,并且它创建了许多重复的serialNumbers(相同的SerialNumbers).所以我在事务中添加了一个具有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
Run Code Online (Sandbox Code Playgroud)

我甚至将获取序列号的函数直接复制到存储过程而不是UDF函数调用中,并且仍然有重复的serialNumbers.So,存储过程行如何创建类似c#lock(){}块的东西.顺便说一句,我必须使用相同的模式实现事务序列号,我不能将serialNumber更改为任何其他标识字段或任何其他.由于某些原因我需要在数据库中生成serialNumber而我不能将SerialNumber生成移动到应用程序级别.


对不起,但我已经在函数中没有READUNCOMMITTED尝试了这个,但我仍然得到重复的SerialNumbers.

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

Aar*_*ght 5

你有READUNCOMMITTEDUDF.这将导致它忽略其他事务持有的任何独占锁.

SET TRANSACTION ISOLATION LEVEL SERIALIZABLEapplock不同,它不是数据库中的"关键部分",它只是控制事务中后续语句的锁定行为.

取出READUNCOMMITTED它应该按照你的预期开始工作.

当然,这忽略了你基本上重新实现了一个IDENTITY列的事实.如果您的序列号确实是增量的,那么您应该抛弃所有这些并用一个简单的IDENTITY列替换它.你声称你"不能",但没有为该陈述提供任何理由; 它看起来像你对我几乎肯定可以.