我开始使用SQL Server数据库,我很难理解Transaction Isolation Levels
以及它们如何锁定数据。
我正在尝试完成以下简单任务:
SELCT COUNT(*) FROM MyTable WHERE Id = {idParam}
COUNT
语句返回0,请插入此ID和计数器:
INSERT INTO MyTable(Id, Counter) VALUES({idParam}, {counterParam})
COUNT
语句返回1,则更新现有记录:UPDATE MyTable SET Counter = Counter + {counterParam} WHERE Id = {idParam}
现在,我知道我必须将整个存储过程包装在一个事务中,并且根据this MS article,适当的隔离级别将是SERIALIZABLE
(它说:没有其他事务可以修改具有的数据已被当前事务读取,直到当前事务完成)。如果我错了,请纠正我。
假设我使用ID = 1调用过程,因此第一个查询woluld为SELCT COUNT(*) FROM MyTable WHERE SomeId=1
(第一个事务开始)。然后,在执行此查询之后,立即调用ID为2的过程(第二个事务开始)。
我无法理解的是在这种情况下执行存储过程期间会锁定多少数据:
答案 0 :(得分:0)
如果您的过滤器位于某个索引上,那将会锁定哪些内容。因此,无论行是否已存在,它都会在事务持续期间被锁定。不过要小心 - 很容易将行锁变成更糟糕的东西,特别是全桌锁。当然,以这种方式引入死锁很容易:)
但是,我建议采用不同的方法。首先,尝试插入。如果它有效,你就完成了 - 如果它没有,你知道你可以安全地进行原子更新。非常快,非常便宜,非常可靠:)