当前位置: 首页 > 知识库问答 >
问题:

如何防止选择和更新之间的竞争条件

墨安阳
2023-03-14

我正在做分类帐模块。在这个过程中,我必须按顺序完成这些任务

  1. 从源中选择余额(table 1 row1)
  2. 从目标中选择余额(table 1 row2)
  3. 用一些逻辑修改余额
  4. 更新源的余额(table 1 row1)
  5. 更新目标余额(table 1 row2)
  6. 提交更改
  7. 将事务插入到事件表中。

在多线程环境中,线程在前一个线程更新和提交之前获得余额。在Postgres中,锁被强加给正在被访问的行,直到线程提交。在这种情况下,我看到了一种病态。

尝试对整个模式使用同步块。没有帮助。不能使用SELECT from UPDATE,因为更改余额的逻辑取决于其他操作。

以下是一些日志,在 [1] 线程转到更新部分之前,其他线程收集现有余额。

[DEBUG] [2016-12-15 10:49:53,893] [1] - Src Ledger_book_idLB001
[DEBUG] [2016-12-15 10:49:53,893] [1] - Src Balance2500.0
[DEBUG] [2016-12-15 10:49:53,897] [1] - Dest Ledger_book_idLB002
[DEBUG] [2016-12-15 10:49:53,897] [1] - Dest Balance0.0
[DEBUG] [2016-12-15 10:49:53,898] [15] - Src Ledger_book_idLB001
[DEBUG] [2016-12-15 10:49:53,898] [15] - Src Balance2500.0
[DEBUG] [2016-12-15 10:49:53,899] [16] - Src Ledger_book_idLB001
[DEBUG] [2016-12-15 10:49:53,899] [16] - Src Balance2500.0
[DEBUG] [2016-12-15 10:49:53,900] [16] - Dest Ledger_book_idLB002
[DEBUG] [2016-12-15 10:49:53,900] [15] - Dest Ledger_book_idLB002

任何帮助都值得赞赏:)如果对情况有任何具体疑问,请发表评论。

共有1个答案

伊富
2023-03-14

从文档中

当锁定子句出现在子选择中时,锁定的行是子查询返回给外部查询的行。这可能涉及比单独检查子查询所建议的更少的行,因为来自外部查询的条件可能用于优化子查询的执行。

所以你可以这样做...

您还应该阅读CTE的页面,尤其是DATA-MODIFYING

WITH s1 AS (
  SELECT balance FROM source
  FOR UPDATE
), s2 AS (
  SELECT balance destination
  FOR UPDATE
), u1 AS (
  UPDATE source SET balance = ...
  WHERE... -- potential join to S2 if you need destination
  RETURNING -- whatever you need (if anything)
), u2 AS (
  UPDATE source SET balance = ...
  WHERE... -- potential join to S1 if you need source
  RETURNING -- whatever you need (if anything)
)
INSERT INTO transactions (foo,date) VALUES (bar,now());
 类似资料:
  • 我在使用 PostgreSQL 的 ActiveRecord 中遇到了竞争条件,我正在读取一个值,然后递增它并插入一条新记录: 按比例,多个线程将同时读取并写入的相同值。将其封装在事务中并不能修复竞争条件,因为SELECT不会锁定表。我不能使用自动递增,因为不是唯一的,它只在给定特定的时才是唯一的。我看到3种可能的修复方法: > < li> 显式使用postgres锁(行级锁?) 使用唯一约束并在

  • 在使用ACK时,有没有一种简单的方法实现类似于“锁定”的东西来防止RabbitMQ队列中的竞争条件? 我有以下问题--我有几个客户机使用ACK使用队列。每当客户端收到消息时,他就会确认并处理消息。但是,如果由于某种原因处理失败,我希望消息返回到队列。

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

  • 我有一个具有2级层次结构的TreeView控件。如果选择了第二级的项目,并且用户单击了另一个项目,我需要询问他是否确定要移动到另一个项目。如果他的答案是“否”,我需要阻止选择另一个TreeViewItem。 我试着这样做: 以一种有效的方式。但是,问题是我得到了两次OnMouseDown事件:第一级项目和第二级项目。例如,对于这棵树:俄罗斯-莫斯科-皮特美国-纽约-波士顿如果我单击波士顿,我将获得

  • 问题内容: 我正在开发的应用程序中存在潜在的竞争状况,我想在查询中考虑和避免这种情况。 总结应用程序流程… 在表中创建一个新行: 通过查看对时间敏感的表格,找出Bar先生是否是获胜者: 如果他是赢家,请相应地更新他的条目行: 由于每个奖项只能颁发一次,因此我需要消除比赛条件的任何可能性,在这种情况下,另一个过程可以查询奖项表并更新上述步骤2和3之间的条目表。 我一直在做一些研究,发现了大量关于事务

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