首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >事务中的乐观并发

事务中的乐观并发
EN

Stack Overflow用户
提问于 2022-03-18 12:48:38
回答 1查看 115关注 0票数 0

在试图修复由于并发冲突导致的数据错误时,我意识到我不完全确定SQL Server中乐观并发的工作方式。假设READ_COMMITTED隔离级别。一个类似的例子:

代码语言:javascript
运行
复制
BEGIN TRAN

SELECT * INTO #rows FROM SourceTable s WHERE s.New = 1

UPDATE d SET Property = 'HelloWorld' FROM DestinationTable d INNER JOIN #rows r ON r.Key = d.Key

UPDATE s SET Version = GenerateRandomVersion() FROM SourceTable s
INNER JOIN #rows r on r.Key = s.Key AND r.Version = s.Version

IF @@ROWCOUNT <> SELECT COUNT(*) FROM #rows
    RAISEERROR
END IF

COMMIT TRAN

这完全是原子/线程安全吗?

UPDATE s上的ON子句应通过版本和ROWCOUNT检查防止并发更新。但这真的是真的吗?下面类似的查询呢?

代码语言:javascript
运行
复制
BEGIN TRAN

SELECT * INTO #rows FROM SourceTable s WHERE s.New = 1

UPDATE s SET New = 0 AND Version = GenerateRandomVersion() FROM SourceTable s
INNER JOIN #rows r on r.Key = s.Key AND r.Version = s.Version

IF @@ROWCOUNT <> SELECT COUNT(*) FROM #rows
    RAISEERROR
END IF

UPDATE d SET Property = 'HelloWorld' FROM DestinationTable d INNER JOIN #rows r ON r.Key = d.Key

COMMIT TRAN

我在这里担心的是,上述脚本的并发执行将到达UPDATE的语句,得到一个@@ROWCOUNT,该@ROWCOUNT是瞬态的/尚未实际提交给DB,因此这两个线程/执行都将继续通过IF语句,并执行重要的UPDATE d语句,在这种情况下,这个语句是幂等的,但在我最初的生产用例中不是这样。

EN

回答 1

Stack Overflow用户

发布于 2022-03-18 14:09:46

我认为您想要做的是删除脚本中非常小的竞赛条件,使其尽可能基于设置。

代码语言:javascript
运行
复制
BEGIN TRAN

DECLARE @UpdatedSources Table (Key INT NOT NULL);

UPDATE s SET New = 0 
FROM SourceTable s
WHERE s.New = 1
OUTPUT Inserted.Key into @UpdatedSources

UPDATE d SET Property = 'HelloWorld' 
FROM DestinationTable d 
INNER JOIN @UpdatedSources r ON r.Key = d.Key

COMMIT TRAN

我认为表中的“version”列让人感到困惑--您试图在表中构建原子性,而不仅仅是让DB事务处理它。使用上面的脚本,将锁定New=1的行,直到事务提交,因此后续的尝试只会找到“实际”的新行或new=0的行。

评论后的更新

要演示表上的锁定,如果您希望看到它,则可以尝试启动死锁。如果要与第一个查询同时运行此查询,我认为您最终可能会陷入死锁,但取决于这些查询的运行速度,您可能很难看到它:

代码语言:javascript
运行
复制
BEGIN TRAN

SELECT *
FROM DestinationTable d 
INNER JOIN SourceTable ON r.Key = d.Key
WHERE s.New = 1

UPDATE s SET New = 0 
FROM SourceTable s
WHERE s.New = 1
    
COMMIT TRAN
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/71527263

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档