有时我需要获取唯一的ID并将其与记录一起存储,但是我无法使用标识列。因此,我有了一个使用标签字段和整数提供唯一ID的表。当需要唯一的ID时,我将调用存储过程并传递标签,它会吐出与之关联的下一个ID。当然,在具有并发事务的环境中做到这一点很重要。也就是说,对于给定的标签,存储过程永远不应返回相同的值两次。由于对事务隔离的了解有限,因此我需要执行以下操作:
1)将事务隔离级别设置为可序列化
2)从UniqueIdTable WHERE标签SELECT ID = @inputLabel
3)更新UniqueIdTable SET ID = ID + 1 WHERE标签= @inputLabel
4)返回在2)中检索到的ID
但这实际上安全吗?即使使用可序列化的隔离,两个线程是否仍然可以并发执行直到步骤2)?我的理解是,最高的隔离级别仅保证单个事务将执行而不会出现幻像行或更改其他线程中的数据的情况。如果是这种情况,两次同时调用GetID函数可能会返回相同的值。
我是否对隔离级别有误解?我如何保证不会发生这种情况?
我还有另一个问题需要解决。假设我有一个表,其中包含一个字段,其中包含第二个表的外键。最初,第一个表中的记录在第二个表中没有对应的记录,因此我将NULL存储在该字段中。现在,在某个时候,用户运行了一个操作,该操作将在第二个表中生成一条记录,并使第一个表链接到该记录。这始终是一对一的关系,因此,如果两个用户同时尝试生成记录,则会创建并链接到单个记录,另一个用户会收到一条消息,说明该记录已存在。如何确保不会在并发环境中创建重复项?
您可以使用output递增 并 获取更新语句中的ID 。
update UniqueIdTable set ID = ID + 1 output deleted.ID where label = @inputLabel