【发布时间】:2011-12-29 15:17:49
【问题描述】:
我有一个包含用户设置(如窗口位置)的小表,只是一个简单的名称=值对表,其中名称需要是唯一的:
CREATE TABLE dbo.[Settings]
(
[Name] [nvarchar](100) NOT NULL,
[Value] [nvarchar](4000) NOT NULL,
CONSTRAINT [PK_Settings] PRIMARY KEY CLUSTERED
(
[Name] ASC
) ON [PRIMARY]
) ON [PRIMARY]
当我存储更改的设置时,我开始一个事务,尝试更新值,如果更新失败(因为记录还不存在)我插入一条新记录:
// Begin Transaction
cmd.CommandText = "UPDATE dbo.[Settings] SET [Value] = @value WHERE [Name] = @name";
cmd.Parameters.AddWithValue("@value", value);
cmd.Parameters.AddWithValue("@name", name);
int cmdrc = cmd.ExecuteNonQuery();
if (cmdrc != 1)
{
cmd.CommandText = "INSERT INTO dbo.[Settings] ([Name], [Value]) VALUES (@name, @value)";
cmd.ExecuteNonQuery();
}
// Commit Transaction
我的问题:如果两个线程碰巧同时尝试存储同名的值(这种情况很少发生,但仍然如此),就会发生冲突:
两个线程都尝试更新,两个线程都得到cmdrc==0,两个线程都尝试插入新值,只有一个会成功,另一个会得到一个SqlException。
我以为事务会锁定记录,但似乎由于在Update语句上没有找到记录,它没有被锁定,所以尝试更新相同'name'值的其他线程不会被阻塞, 竞争条件发生。
有没有办法让 SQL Server 锁定关键字,即使没有找到它的记录?
【问题讨论】:
标签: sql-server transactions locking