Oracle 和 Postgresql的死锁检测和处理有较大区别。
主要差别在于 :
1. 死锁被检测到的属于哪个SESSION?Oracle随机检出,从实验来看应该是第一个启动的死锁事务。而Postgresql是死锁发生时的最后一个事 务,与ORACLE相反(从PG的deadlock_timeout参数可以看出Postgresql的死锁检测不是随机的,而是可预见的。This is the amount of time,in milliseconds,to wait on a lock before checking to see if there is a deadlock condition.)。
2. 死锁被检测到之后的处理上的差别,oracle允许单个事务中的部分sql执行成功,部分sql执行失败(其实这是非常严重的缺陷)。而Postgresql不允许事务中的部分sql语句执行成功,要么全部成功,要么全部失败。
如图:
Postgresql 模拟死锁场景和检测结果,
Oracle 模拟死锁场景和检测结果,
Postgresql参数 : deadlock_timeout = 1s 死锁检查会消耗部分数据库资源,如果数据库压力比较大的话可以考虑调大这个值。 SESSION A : digoal=> begin; BEGIN Time: 0.122 ms digoal=> update tbl_test set id=id+1 where id=100; UPDATE 1 Time: 0.379 ms SESSION B : digoal=> begin; BEGIN Time: 0.126 ms digoal=> update tbl_test2 set id=id+1 where id=100; UPDATE 1 Time: 0.437 ms SESSION C : digoal=> begin; BEGIN digoal=> update tbl_test1 set id=id+1 where id=100; UPDATE 1 SESSION A : digoal=> update tbl_test2 set id=id+2 where id=100; SESSION B : digoal=> update tbl_test1 set id=id+3 where id=100; SESSION C : digoal=> update tbl_test set id=id+4 where id=100; ERROR: deadlock detected DETAIL: Process 11953 waits for ShareLock on transaction 4232; blocked by process 2873. Process 2873 waits for ShareLock on transaction 4233; blocked by process 6616. Process 6616 waits for ShareLock on transaction 4234; blocked by process 11953. HINT: See server log for query details. SESSION B : UPDATE 1 Time: 7839.728 ms SESSION A : UPDATE 0 Time: 40903.601 ms digoal=> commit; COMMIT Time: 0.099 ms SESSION C : digoal=> commit; ROLLBACK Time: 0.196 ms 注意到在Postgresql中,整个SESSION C回滚了。 Oracle : SESSION A: sql> update tbl_test set id=id+1 where id=100; 1 row updated. Elapsed: 00:00:00.00 SESSION B: sql> update tbl_test2 set id=id+1 where id=100; 1 row updated. Elapsed: 00:00:00.01 SESSION C: sql> update tbl_test1 set id=id+1 where id=100; 1 row updated. Elapsed: 00:00:00.00 SESSION A: sql> update tbl_test2 set id=id+2 where id=100; SESSION B: sql> update tbl_test1 set id=id+3 where id=100; 0 rows updated. Elapsed: 00:00:39.50 SESSION C: sql> update tbl_test set id=id+4 where id=100; 0 rows updated. Elapsed: 00:00:17.34 SESSION A: update tbl_test2 set id=id+2 where id=100 * ERROR at line 1: ORA-00060: deadlock detected while waiting for resource Elapsed: 00:00:18.05 SESSION A: sql> commit; Commit complete. Elapsed: 00:00:00.01 SESSION B: sql> commit; Commit complete. Elapsed: 00:00:00.00 SESSION C: sql> commit; Commit complete. Elapsed: 00:00:00.01 显然,ORACLE的SESSION A检测到了死锁,并且COMMIT后SESSION A部分sql执行成功。 sql> select * from tbl_test where id>=100; ID ---------- 101 Elapsed: 00:00:00.00 Oracle 允许事务中部分sql执行成功,部分失败的严重缺陷 : 举个简单的例子:充值。 A花了100元购买100个斯凯币。 update tbl_account_rmb set amount=amount-100 where id='A'; success update tbl_account_kb set amount=amount+100 where id='A'; deadlock,Failed. commit; 此时A的100元花出去了,但是KB没有充值到账。
原文链接:https://www.f2er.com/postgresql/196920.html