Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Multithreading 如何防止选择和更新之间的竞争条件_Multithreading_Postgresql_Jdbc_Locking - Fatal编程技术网

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

Multithreading 如何防止选择和更新之间的竞争条件,multithreading,postgresql,jdbc,locking,Multithreading,Postgresql,Jdbc,Locking,我正在做一个分类账模块。在这个过程中,我必须按顺序完成这些任务 从来源选择余额(表1第1行) 从目的地选择余额(表1第2行) 用一些逻辑修改平衡 更新来源的余额(表1第1行) 更新目的地的余额(表1第2行) 提交更改 将事务插入到事务表中 在多线程环境中,线程在前一个线程更新和提交之前获得平衡。 在Postgres中,在线程提交之前,对正在访问的行施加锁。在这种情况下,我看到了一个幻觉 尝试对整个模式使用同步块。没有帮助。 无法使用“从更新中选择”,因为更改余额的逻辑取决于其他操作 以下是一些日

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

  • 从来源选择余额(表1第1行)
  • 从目的地选择余额(表1第2行)
  • 用一些逻辑修改平衡
  • 更新来源的余额(表1第1行)
  • 更新目的地的余额(表1第2行)
  • 提交更改
  • 将事务插入到事务表中
  • 在多线程环境中,线程在前一个线程更新和提交之前获得平衡。 在Postgres中,在线程提交之前,对正在访问的行施加锁。在这种情况下,我看到了一个幻觉

    尝试对整个模式使用同步块。没有帮助。 无法使用“从更新中选择”,因为更改余额的逻辑取决于其他操作

    以下是一些日志,[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
    
    感谢您的帮助:)如果您对情况有任何疑问,请发表意见。

    当子SELECT中出现锁定子句时,锁定的行是子查询返回到外部查询的行。这可能比单独检查子查询所建议的行少,因为外部查询的条件可能用于优化子查询的执行

    所以你可以这样做

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


    您可以使用
    serializable
    隔离级别。如果您正在更新
    源代码
    ,是什么使它成为
    源代码
    ?来源和目的地的区别是什么?@EvanCarroll所说的来源我指的是来源账户。。。我正在尝试借记源中的金额,贷记目标中的金额。无法使用“从更新中选择”您的意思是
    SELECT。。。是否要更新
    ?很难理解您的日志,但我认为您的问题在于目标行的更改(其他行将被更新,而不是所选的行),对吗?是的,它是
    select。。。从更新
    。我希望日志中的线程[15]和[16]等到[1]完成更新和提交。你可以在日志中看到它。请参考预期订单并与日志进行比较。感谢您的回复:)
    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());