sql-server - 如果不存在则插入以避免竞争条件
问题描述
如何确保以下语句没有竞争条件?
IF NOT EXISTS (select col1 from Table1 where SomeId=@SomeId)
INSERT INTO Table1 values (@SomeId,...)
IF NOT EXISTS (select col1 from Table2 where SomeId=@SomeId)
INSERT INTO Table2 values (@SomeId,...)
这够了吗
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE
BEGIN TRAN
IF NOT EXISTS (SELECT col1 FROM Table1 WITH (UPDLOCK) WHERE SomeId=@SomeId)
INSERT INTO Table1 VALUES (@SomeId,...)
COMMIT TRAN
BEGIN TRAN
IF NOT EXISTS (SELECT col1 FROM Table2 WITH (UPDLOCK) WHERE SomeId=@SomeId)
INSERT INTO Table2 VALUES (@SomeId,...)
COMMIT TRAN
解决方案
是的。足够了。将事务隔离级别设置为可序列化将创建SomeId=@SomeId
在您运行 select 时覆盖的键锁——这将防止其他进程SomeId=@SomeId
在您的事务运行时插入具有相同键 ( ) 的值。
该WITH(UPDLOCK)
提示将导致 SELECT 获取所选行(如果存在)的更新锁。这将防止其他事务在您的事务运行时修改这些行(如果它们在选择时存在)。
看起来您并不需要WITH(UPDLOCK)
提示,因为如果记录已经存在,您将立即提交事务。如果您想在记录确实存在的情况下在提交之前做其他事情,您可能需要这个提示 - 但实际上,您似乎不需要。
推荐阅读
- javascript - 使用 C3.js 为 Timeseries X 轴创建堆积条形图
- mezzio - hal 中生成的不完整链接(zend-expressive-hal + zend-router)
- javascript - 将日志文件文本解析为 JSON
- reactjs - 请求的资源上不存在“Access-Control-Allow-Origin”标头。亚马逊 S3
- python - 将单个元素列表视为 Python 中的标量
- python - 显示文件中以特定字母开头的单词
- c# - HtmlAgilityPack - 如何在使用 selectnodes 时首先选择标签 href
- r - 删除 R 中包含值低于 0.10(在所有行中)的所有行
- python - 在 Python 中为安全系统处理电子邮件
- r - R:Survminer 双图