使用Postgres处理JDBC时...
Isolationlevel =" Read committed"
当我在一些操作后尝试更新表时,我在多线程环境中遇到了同样的死锁。 所以我尝试使用多个查询,如下所示
ps = con.prepareStatement("UPDATE TableA SET column1=column1-? WHERE column2=? and column3=?;"
+ "UPDATE TableA SET column1=column1+? WHERE column2=? and column3=?;");
以下是错误的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.
在这个多线程环境中,我期望TableA的行被锁定为2个语句并避免死锁。
我看到类似的情景解释了 Postgres Docs
我找不到任何方法来避免这种死锁。任何帮助表示赞赏。感谢
P.S:Autocommit已经设置为FALSE并尝试使用带有单个UPDATE查询的preparedStatements。
关于多个查询 - > Multiple queries in one Preparedstatement和this表明postgres不需要任何其他配置。
答案 0 :(得分:7)
@Nick Barnes在评论中引用了我分享的链接。
防止死锁的最佳方法通常是避免死亡 确定使用数据库的所有应用程序都获得锁定 多个对象采用一致的顺序。
特别是对于所提到的更新死锁,更新顺序会导致死锁。
示例强>:
UPDATE Table SET ... WHERE id= 1;
UPDATE Table SET ... WHERE id= 2;
和
UPDATE Table SET ... WHERE id= 2;
UPDATE Table SET ... WHERE id= 1;
一般解决方案是根据ID 订购更新。这就是一致的顺序意味着什么。
我一直都不明白,直到我为这个僵局而斗争。
答案 1 :(得分:2)
根据我的经验,PostgreSQL中的死锁最有可能发生在"现实生活中#34;当你"交叉"更新2个长时间运行的事务。 (解释如下)。甚至很难模拟PG上的死锁。这是一个例子 - http://postgresql.freeideas.cz/simulate-deadlock-postgresql/ 所以经典的死锁意味着:
所以我建议你尽快提交交易。