如何确保两个事务具有相同版本的数据?

时间:2017-08-21 01:18:32

标签: sql sql-server tsql transactions

我有一个包含A列和B列的表。让我们假设两者都是布尔值。这些列将由某些程序代码中的函数访问。

一个函数首先读取A,如果为真,它将修改B(将其设置为false)。

第二个函数将首先读取B,如果它具有一定的值(例如,真),它将修改A(将其设置为false)。

这些功能可以按任何顺序运行。

我遇到的问题是这两者都是相互依赖的(如果第二个函数读取B为真,则将A设置为false),这可能导致数据库的状态不正确(A为假而B是假的。)

理想情况下,我会创建触发第二次等待的函数,直到第一次完成行,然后开始工作。但是,从我查看过的内容来看,3个保护级别中没有一个会禁止该函数读取该行,只能让它等到写入。

我想避免的一个场景是:

Function1启动。它读为A(真)。 function2现在启动并读取B(true)。 function1将B设置为false。 function2将A设置为false。我留下2假,这不应该发生。

正确的方案可能如下所示: 功能1开始。它读为A(真)。 function2启动,但必须等待function1完成。 Function1将B设置为false。 function2现在可以访问B并看到它是假的,并且停止/发出错误信号。

我可以使用数据库机制以某种方式完成这项工作吗?

2 个答案:

答案 0 :(得分:3)

@Squirrel建议使用Application Lock,或者将事务编码为SELECT UPDLOCK行(其中conflicts带有其他U锁和X锁),或者与所有冲突的XLOCK其他锁。没有隔离级别会阻止并发读取行。

另请注意,这些锁仅阻止来自其他锁定事务的读取。如果您处于SNAPSHOT或READ COMMITTED SNAPSHOT,那么持有U或X锁的交易不会阻止一致的读取。

答案 1 :(得分:1)

在选择数据以决定更新之前,您需要使用假更新手动锁定两个表中的两行。

示例:

else