如何避免更新死锁

Vam*_*har 8 postgresql multithreading deadlock jdbc sql-update

在使用Postgres处理JDBC时......

Isolationlevel ="读取已提交"

当我在一些操作后尝试更新表时,我在多线程环境中遇到了同样的死锁.所以我尝试使用多个查询,如下所示

  ps = con.prepareStatement("UPDATE TableA SET column1=column1-? WHERE column2=? and column3=?;"  
                          + "UPDATE TableA SET column1=column1+? WHERE column2=? and column3=?;");
Run Code Online (Sandbox Code Playgroud)

以下是错误的postgresql日志

2016-12-19 12:25:44 IST STATEMENT:  UPDATE TableA SET column1=column1+$1 WHERE column2=$2 and column3=$3
2016-12-19 12:25:44 IST FATAL:  connection to client lost
2016-12-19 12:25:45 IST ERROR:  deadlock detected
2016-12-19 12:25:45 IST DETAIL:  Process 8524 waits for ShareLock on transaction 84942; blocked by process 12520.
    Process 12520 waits for ShareLock on transaction 84940; blocked by process 20892.
    Process 20892 waits for ExclusiveLock on tuple (1,5) of relation 25911 of database 24736; blocked by process 8524.
    Process 8524: UPDATE TableA SET column1=column1-$1 WHERE column2=$2 and column3=$3
    Process 12520: UPDATE TableA SET column1=column1-$1 WHERE column2=$2 and column3=$3
    Process 20892: UPDATE TableA SET column1=column1-$1 WHERE column2=$2 and column3=$3
2016-12-19 12:25:45 IST HINT:  See server log for query details.
2016-12-19 12:25:45 IST CONTEXT:  while locking tuple (1,12) in relation "TableA"
2016-12-19 12:25:45 IST STATEMENT:  UPDATE TableA SET column1=column1-$1 WHERE column2=$2 and column3=$3
2016-12-19 12:25:45 IST LOG:  could not send data to client: No connection could be made because the target machine actively refused it.
Run Code Online (Sandbox Code Playgroud)

在这个多线程环境中,我期望TableA的行被锁定为2个语句并避免死锁.

我在Postgres Docs中看到了类似的场景

我找不到任何方法来避免这种僵局.任何帮助表示赞赏.谢谢

PS:Autocommit已设置为FALSE并尝试使用带有单个UPDATE查询的preparedStatements.

关于多个查询 - > 一个Prepared语句中的多个查询,表明postgres不需要任何其他配置.

Vam*_*har 7

正如@Nick Barnes在我分享的链接评论中所引用的那样.

防止死锁的最佳方法通常是通过确保使用数据库的所有应用程序以一致的顺序获取多个对象的锁来避免死锁.

特别是对于所提到的更新死锁,更新顺序会导致死锁.

示例:

UPDATE Table SET ... WHERE id= 1;
UPDATE Table SET ... WHERE id= 2;
Run Code Online (Sandbox Code Playgroud)

UPDATE Table SET ... WHERE id= 2;
UPDATE Table SET ... WHERE id= 1;
Run Code Online (Sandbox Code Playgroud)

一般的解决方案是根据id 订购更新.这就是一致的顺序意味着什么.

直到我为这个僵局而斗争,我才明白这一点.