) TestPro; TestPro ( @Id INT ) ((100)) ( i INT ); ; Test OUTPUT DELETED.Id Id = @Id; ( SELECT i FROM @updated ) INSERT INTO Test ( Id, Name, counter ) VALUES ( @Id, @Name, 1 ); COMMIT GO
经过多次认证也是零错误,貌似通过表变量形式实现可行。
解决方案七(提升隔离级别+Merge)通过Merge关键来实现存在即更新否则则插入,同时我们应该注意设置隔离级别为 SERIALIZABLE 否则会出现插入重复键问题,代码如下:
) TestPro; TestPro ( @Id INT ) ((100)) MERGE Test USING ( Id ) AS source .Id .MATCHED ) VALUES ( @Id, @Name, 1 ); COMMIT GO
多次认证无论是并发100个线程还是并发200个线程依然没有异常信息。
总结本节我们详细讨论了在并发中如何处理存在即更新,否则即插入问题的解决方案,目前来讲以上三种方案可行。
解决方案一(最高隔离级别 + 更新锁)) TestPro; TestPro ( @Id INT ) ((100)) BEGIN TRANSACTION; UPDATE dbo.Test WITH ( UPDLOCK, HOLDLOCK ) Id = @Id; ) BEGIN INSERT dbo.Test ( Id, Name, ) VALUES ( @Id, @Name, 1 );
解决方案二(最高隔离级别 + 表变量)) TestPro; TestPro ( @Id INT ) ((100)) ( i INT ); ; Test OUTPUT DELETED.id id = @id; ( SELECT i FROM @updated ) INSERT INTO Test ( Id, Name, counter ) VALUES ( @Id, @Name, 1 ); COMMIT GO
解决方案三(最高隔离级别 + Merge)) TestPro; TestPro ( @Id INT ) ((100)) MERGE Test USING ( Id ) AS source .Id .MATCHED ) VALUES ( @Id, @Name, 1 ); COMMIT GO
暂时只能想到这三种解决方案,个人比较推荐方案一和方案三, 请问您有何高见,请留下您的评论若可行,我将进行后续补充。