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

在PostgreSQL中处理竞争条件

白弘伟
2023-03-14
问题内容

我有几个工作人员,每个工作人员都拥有与PostgreSQL的连接。工人用不同的桌子操纵。

工作人员处理来自系统外部的并行请求。被访问的表之一是用户表。当收到一些信息时,我首先需要确保表中有该用户的记录。如果没有记录,我希望首先创建一个。

我正在使用以下成语:

if [user does not exist] then [create user]

的代码[user does not exist]是:

SELECT id FROM myschema.users WHERE userId='xyz'

然后测试是否返回任何行。

的(简化)代码[create user]为:

INSERT INTO myschema.users VALUES ('xyz')

当我的系统处理与 同一 用户有关 不同信息的并行流时,我经常会收到PostgreSQL错误:

Key (id)=(xyz) already exists

发生这种情况是因为该SELECT命令不返回任何行,然后另一个工作人员创建了用户,而我的任何工作人员都试图执行该操作,从而导致示例性的并发错误。

根据PostgreSQL文档,默认情况下,每当我隐式启动事务时,只要我不提交该表,该表就会被锁定。我没有使用自动提交,我只在块中提交事务,例如在整个if- else块之后。

确实,我可以将这些if- else东西直接放入SQL中,但是它通常不能解决我的锁定问题。我以为“获胜者会全力以赴”范例将起作用,并且设法执行SELECT命令的第一个工作人员将拥有锁,直到调用为止COMMIT

我在SO上阅读了许多不同的主题,但是我仍然不确定什么是正确的解决方案。我应该使用表的显式锁定,因为隐式锁定不起作用?如何确保只有一个工人同时拥有一张桌子?


问题答案:

您必须关心事务隔离级别。应将其设置为“ SERIALIZABLE”。

原因是Phantom Reads-事务不会锁定整个表,而只会锁定已被事务读取的行。

因此,如果另一个事务插入新数据,则尚未锁定它们,并且会出现错误。

可序列化可通过阻止所有其他事务来避免这种情况,直到完成这一事务为止。

您可以通过

SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;

文档:http :
//www.postgresql.org/docs/9.1/static/transaction-
iso.html



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

  • 我在使用 PostgreSQL 的 ActiveRecord 中遇到了竞争条件,我正在读取一个值,然后递增它并插入一条新记录: 按比例,多个线程将同时读取并写入的相同值。将其封装在事务中并不能修复竞争条件,因为SELECT不会锁定表。我不能使用自动递增,因为不是唯一的,它只在给定特定的时才是唯一的。我看到3种可能的修复方法: > < li> 显式使用postgres锁(行级锁?) 使用唯一约束并在

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

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

  • 我已经编写了一个计时器,它将测量任何多线程应用程序中特定代码的性能。在下面的计时器中,它还将用x毫秒的调用次数填充映射。我将使用这个图作为我的直方图的一部分来做进一步的分析,比如调用的百分比花费了这么多毫秒等等。 例如,这是我将使用上面的计时器类来衡量多线程应用程序中特定代码的性能的方式: 现在我的问题是,如果你看一下getDuration方法,我也会在我的地图中填充一些信息,比如花了x毫秒的调用

  • 问题内容: (注意:这是针对MS SQL Server的) 假设您有一个具有主键标识列和CODE列的表ABC。我们希望此处的每一行都有一个唯一的,顺序生成的代码(基于一些典型的校验位公式)。 假设您有另一个仅具有一行的表DEF,该表存储下一个可用的CODE(想象一个简单的自动编号)。 我知道像下面这样的逻辑将呈现一种竞争状态,其中两个用户可能最终得到相同的CODE: 我知道,两个用户可能会卡在步骤