【发布时间】:2011-12-05 21:44:40
【问题描述】:
我有一个将数据插入数据库 (SQL Server 2008) 的进程,我无法修改其架构。该表有一个 int PK,但没有自动增量。因此,我需要获取最大的 id,将其递增然后插入(并返回新的 id)。该事务还需要同时更新许多其他表。我显然是想避免同时插入的竞争条件。
Begin Transaction (Read Committed)
DECLARE @MyVar int;
--here be the race condition
SET @MyVar = (( SELECT MAX(value) FROM MyTable WITH (ROWLOCK, XLOCK, HOLDLOCK)) + 1);
INSERT INTO MyTable ....
UPDATE MyOtherTable SET Val = @MyVar WHERE WhatEver
SELECT MyRetValName = @MyVar
INSERT INTO MyThirdTable ...
Commit Transaction
事务隔离级别和表锁定提示是否足以防止竞争条件,还是我需要 UPDLOCK 而不是 ROWLOCK? (如果插入失败,我有一个单独的“重试”过程。)
【问题讨论】:
-
您可以添加一个额外的表吗?如果是这样,就有可能想出一个阻塞更少的解决方案。
-
@Martin 不幸的是,目前不允许添加额外的表,但如果没有其他可接受的性能方法,可能会提出一个案例。这之前是通过 MyTable 上的 Serializable 隔离级别和全表锁实现的。我的任务是优化,因为该解决方案导致了很多性能问题。
-
有什么理由不能将其更改为
identity列吗? -
@Martin 我无法将其更改为 Identity 列,因为这是属于不同的现成应用程序的数据库。此应用程序中的代码对该特定列进行了大量处理,并将其用于许多不适当的事情。我担心如果我不以类似于应用程序插入数据的方式插入数据,我会导致严重的下游问题。
标签: sql sql-server-2008 locking