当前位置: 首页 > 面试题库 >

SQL Server竞争条件问题

丁业
2023-03-14
问题内容

(注意:这是针对MS SQL Server的)

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

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

我知道像下面这样的逻辑将呈现一种竞争状态,其中两个用户可能最终得到相同的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隔离级别的详细信息

因此,最重要的是隔离级别在这里至关重要,可以控制其他事务进入该级别的访问级别。

笔记。在链接中,关于 “可 序列化
语句”无法读取已被其他事务修改但尚未提交的数据
这是因为锁是在修改行时而不是在Begin Trans发生行时放置的,因此您所做的可能仍然允许另一个事务读取旧值,直到修改该值为止。因此,我将更改逻辑以在阅读时在同一条语句中对其进行修改,从而同时锁定它。

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


 类似资料:
  • 9.1. 竞争条件 在一个线性(就是说只有一个goroutine的)的程序中,程序的执行顺序只由程序的逻辑来决定。例如,我们有一段语句序列,第一个在第二个之前(废话),以此类推。在有两个或更多goroutine的程序中,每一个goroutine内的语句也是按照既定的顺序去执行的,但是一般情况下我们没法去知道分别位于两个goroutine的事件x和y的执行顺序,x是在y之前还是之后还是同时发生是没法

  • 9.6. 竞争条件检测 即使我们小心到不能再小心,但在并发程序中犯错还是太容易了。幸运的是,Go的runtime和工具链为我们装备了一个复杂但好用的动态分析工具,竞争检查器(the race detector)。 只要在go build,go run或者go test命令后面加上-race的flag,就会使编译器创建一个你的应用的“修改”版或者一个附带了能够记录所有运行期对共享变量访问工具的tes

  • 问题内容: 如何停止MySQL中的竞争条件?当前的问题是由一个简单的算法引起的: 从表中选择一行 如果不存在,将其插入 然后会得到重复的行,或者如果您通过唯一/主键阻止它,则会出现错误。 现在,通常我认为事务在这里有所帮助,但是由于该行不存在,所以事务实际上并没有帮助(或者我是否错过了什么?)。 LOCK TABLE听起来有些矫kill过正,尤其是如果该表每秒更新多次。 我唯一想到的其他解决方案是

  • 问题内容: 我有几个工作人员,每个工作人员都拥有与PostgreSQL的连接。工人用不同的桌子操纵。 工作人员处理来自系统外部的并行请求。被访问的表之一是用户表。当收到一些信息时,我首先需要确保表中有该用户的记录。如果没有记录,我希望首先创建一个。 我正在使用以下成语: 的代码是: 然后测试是否返回任何行。 的(简化)代码为: 当我的系统处理与 同一 用户有关 的 不同信息的并行流时,我经常会收到

  • 问题内容: 我有一个订单队列,可通过存储过程由多个订单处理器访问。每个处理器传递一个唯一的ID,该ID用于锁定接下来的20个订单以供自己使用。然后,存储过程将这些记录返回给要处理的订单处理器。 在某些情况下, 多个处理器能够检索相同的“ OrderTable”记录 ,此时它们将尝试同时对其进行操作。这最终会导致在该过程的后期引发错误。 我的下一个动作是允许每个处理器抓住所有可用的订单,然后对处理器