【问题标题】:SQL Server, double insert at the exact same time, unicity BugSQL Server,同时双插入,唯一性Bug
【发布时间】:2015-05-05 15:38:57
【问题描述】:

当以下代码几乎同时被调用两次时,我遇到了麻烦。

DECLARE @membershipIdReturn as uniqueidentifier=null
SELECT @membershipIdReturn = MembershipId 
FROM [Loyalty].[Membership] 
WITH (NOLOCK)
WHERE ContactId = @customerIdFront 
AND 
IsDeleted = 0

IF (@membershipIdReturn IS NULL)
  //InsertStatementHere

调用非常接近(大约千分之三秒),以至于第二个调用也进入了 if 语句。然后解除单一性失败,因为这不应该发生。

这个错误是因为(NOLOCK)吗?我需要它来处理交易问题。

是否有任何解决方法可以纠正这种行为?

谢谢艾尔

【问题讨论】:

  • 为了清楚起见,您是说 [[[SELECT MembershipId FROM [Loyalty].[Membership] WITH (NOLOCK) WHERE Con​​tactId = @customerIdFront AND IsDeleted = 0]]] 不为 NULL,但是在运行后您的 IF 语句 eval 为 true?
  • 两个语句几乎同时运行。对于正常行为,只有第一次运行应该有效 if 语句,第二次不应该是真的,因为第一次运行已经完成了。但是由于调用彼此如此接近,因此两者都运行进入 if 语句。谢谢,艾尔

标签: sql-server sql-server-2012 sql-insert


【解决方案1】:

两种选择

1.使用唯一约束,然后将插入语句放入 Try Catch 块中

ALTER TABLE [Loyalty].[Membership] 
ADD CONSTRAINT uc_ContactId_IsDeleted UNIQUE(ContactId, IsDeleted)

2.使用带有可序列化提示的合并。因此,select和insert之间不会有间隙。

MERGE   [Loyalty].[Membership] WITH (SERIALIZABLE) as T 
USING   [Loyalty].[Membership] as S
ON      ContactId = @customerIdFront 
        AND IsDeleted = 0
WHEN NOT MATCHED THEN
INSERT (MemberName, MemberTel) values ('','');

【讨论】:

  • contactId 和 Isdeleted 已经存在约束,这就是解除唯一性失败的原因。正如我对 Aushin 所说:两个语句几乎同时运行。对于正常的行为,只有第一次运行应该有效 if 语句,第二次不应该是真的,因为第一次运行已经完成了。但是由于调用彼此如此接近,因此两者都运行进入 if 语句。感谢您的强硬回答,我将尝试第二种选择(合并)。会不会影响表演?谢谢 AL
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-04-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多