【发布时间】:2013-05-25 07:59:15
【问题描述】:
我有一张像这样的表
Create Table Items(
[Id] [int] IDENTITY(1,1) NOT NULL PRIMARY KEY,
[UniqueCol] [nvarchar](20) NOT NULL,
[Col] int NOT NULL
)
ALTER TABLE Items ADD CONSTRAINT UN_UniqueCol UNIQUE(UniqueCol)
我在 sql server 2008 中有一个如下所示的存储过程。
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
BEGIN TRANSACTION
if not exists(select * from Items where UniqueCol=uniqueval)
begin
insert into Items (UniqueCol, Col) values (uniqueval, val)
end
select * from Items where UniqueCol = uniqueval
COMMIT TRANSACTION
编辑:此合并工作正常
MERGE INTO Items as Target USING (VALUES(uniqueval)) as source (UniqueCol)
on (source.UniqueCol = Target.UniqueCol)
WHEN MATCHED THEN
update set col = val
WHEN NOT MATCHED BY Target THEN
insert (UniqueCol, col) VALUES (uniqueval, val);
我在 asp.net mvc 中运行一个网站,该网站经常遇到此过程。我在存储过程中执行此操作的原因是,我认为这是处理当两件事情试图同时插入相同的事情时发生的并发问题的最简单的地方。
最后的选择以某种方式将值返回给我在 asp.net mvc 中的模型。我不确定这是否是正确的方法,但是当我尝试从网络服务器调用存储过程时它可以工作
这个存储过程被非常频繁地调用,并且可能同时使用 2 个相同的东西。唯一键可防止存储错误数据,但我希望不必提交并捕获唯一键异常以在并发插入发生时处理它们。我可以在这里锁定表而不破坏性能吗?
我假设这会锁定项目,因此 2 个请求无法同时尝试插入其中,(并导致重复的 id)并且他们无法尝试将相同的值插入表中两次( 2 行,UniqueCol=uniqueval)
我这样做不正确吗?我只是尝试并行调用这个存储过程几次,一次给我一个错误,说存在重复的 PK 违规。
似乎设置事务隔离级别并不意味着以这种方式锁定表。有人可以解释它的含义以及为此类事务锁定表的正确方法吗?
【问题讨论】:
-
我希望“Id”被声明为主键。
-
哦,对不起,是的。我忘了把它放进去。
-
INSERT命令only 锁定它新插入的行 - 没有别的。它不会锁定整张桌子 - 这是一件好事!否则,性能会受到严重影响......
标签: sql asp.net-mvc sql-server-2008 stored-procedures