这更像是一个知识共享帖子。
最近在我的一个项目中,我遇到了一个非常常见的问题,但在面对它之前从未真正考虑过这个问题。 有很多可用的解决方案,但不知怎的,我找不到我想要的那个,我将在这篇文章中分享。我相信你们中的许多人已经知道了下面的解决方案,但对于那些不这样做的人来说,这绝对可以成为一个救生员。 : - )
最近,我正在开发一项Windows服务。该服务应该将一些记录插入到一个长期存在并被其他几个旧服务使用的表中。有一个列(比如说“ID”),它保存一个整数值。写入(可能是几年前)以使Integer插入此表的逻辑如下所述:
逻辑:
代码
SELECT @value = [Value] from [dbo].[Table1] WHERE [Name] = @Name;
UPDATE [dbo].[ Table1] SET [Value] = @value +1 WHERE [Name] = @Name;
SELECT @value = @value+1;
使用的技术存在重大并发问题。
解决此类问题的最佳方法是什么?考虑到这一点在许多不同的应用程序/服务中都有提及?
答案 0 :(得分:2)
显而易见的想法是摆脱这件事并重写这一点。但有时候,特别是当您在这样的区域工作时,某些逻辑,表格,代码已经被其他几个程序引用,这不是一个简单的调用。
我的目标是攻击问题的根源并摆脱它。如果我能做到这一点,那么应该没有真正的影响。 proc的输出是相同的,所以对外界来说没有任何实际改变。 : - )
因此,我对上述语句进行了一些小的调整,以确保每个线程都更新值并读取更新的值。没有更多的冲突,没有更多的脏读。
更新代码
DECLARE @table table(
Value int NOT NULL
);
-- Update the value and output the same into a local table variable
UPDATE [dbo].[Table1] SET [Value] = [Value] + 1 OUTPUT inserted.[Value] INTO @table
WHERE [Name] = @Name
-- Now read the value from the local table variable
SELECT Value FROM @table;
有关输出子句检查https://msdn.microsoft.com/en-us/library/ms177564(v=sql.90).aspx
的更多信息我用parallel.foreach(20,000次)进行了一些测试。我的测试表有两个条目 -