gpt4 book ai didi

SQL Server 竞态条件问题

转载 作者:行者123 更新时间:2023-12-02 14:30:14 24 4
gpt4 key购买 nike

(注意:这适用于 MS SQL Server)

假设您有一个表 ABC,其中包含主键标识列和 CODE 列。我们希望这里的每一行都有一个唯一的、按顺序生成的代码(基于一些典型的校验位公式)。

假设您有另一个表 DEF,只有一行,它存储下一个可用的 CODE(想象一个简单的自动编号)。

我知道像下面这样的逻辑会出现竞争条件,其中两个用户可能最终得到相同的代码:

1) Run a select query to grab next available code from DEF
2) Insert said code into table ABC
3) Increment the value in DEF so it's not re-used.

我知道,两个用户可能会陷入步骤 1),并且最终可能会在 ABC 表中得到相同的 CODE。

处理这种情况的最佳方法是什么?我想我可以围绕这个逻辑包装一个“begin tran”/“commit tran”,但我认为这不起作用。我有一个像这样的存储过程来测试,但是当我从 MS 中的两个不同窗口运行时,我没有避免竞争条件:

begin tran

declare @x int

select @x= nextcode FROM def

waitfor delay '00:00:15'

update def set nextcode = nextcode + 1

select @x

commit tran

有人可以解释一下吗?我认为该事务会阻止其他用户在第一个事务完成之前访问我的 NextCodeTable,但我想我对事务的理解是有缺陷的。

编辑:我尝试将等待移至“更新”语句之后,并且我得到了两个不同的代码......但我怀疑这一点。我在那里有 waitfor 语句来模拟延迟,以便可以轻松地看到竞争条件。我认为关键问题是我对交易如何运作的错误认识。

最佳答案

将事务隔离级别设置为可序列化。
在较低的隔离级别下,其他事务可以读取该事务中已读取(但尚未修改)的行中的数据。所以两个事务确实可以读取到相同的值。在非常低的隔离度(读取未提交)下,其他事务甚至可以在修改数据后(但在提交之前)读取数据...

查看有关 SQL Server 隔离级别的详细信息 here

最重要的是,隔离级别是控制其他事务进入此事务的访问级别的关键部分。

注意。来自 link ,关于可序列化
语句无法读取已被其他事务修改但尚未提交的数据
这是因为锁是在行被修改时放置的,而不是在 Begin Trans 发生时放置的,因此您所做的可能仍然允许另一个事务读取旧值,直到您修改它为止。所以我会改变逻辑,在你读它的同一条语句中修改它,从而同时对其加锁。

begin tran
declare @x int
update def set @x= nextcode, nextcode += 1
waitfor delay '00:00:15'
select @x
commit tran

关于SQL Server 竞态条件问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1683829/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com