我正在阅读《Oracle Database Transactions and Locking Revealed》-第4章“Concurrency and Multiversioning”。在Oracle中,我们有Restart Update(Oracle将从头开始重新启动Update语句)。在Postgresql中有类似的东西吗?
Oracle示例:
Tx1: Update table set col1=0 (old value was col1=2);
<no commit>;
Tx2: Update table set col2=... where col1>0;
Tx1: commit;
Tx2: the update is restared by Oracle Database;
Here是一个链接,描述了“重新启动更新”的含义。
1条答案
按热度按时间laik7k3q1#
这种“重新启动的更新”似乎是Oracle处理
READ COMMITTED
隔离级别问题的方式,我们想要更新的行可能会在我们锁定它之前被并发事务修改。PostgreSQL必须处理同样的问题,但它并没有通过从头开始完整的
UPDATE
语句来解决这个问题。相反,它只检索再次更改的行,检查它是否仍然满足WHERE
条件,并使用更新的行进行进一步处理。文档短语如下:
UPDATE
、DELETE
、SELECT FOR UPDATE
和SELECT FOR SHARE
命令在搜索目标行方面的行为与SELECT
相同:它们将只找到在命令开始时提交的目标行。但是,这样的目标行在被找到时可能已经被另一个并发事务更新(或删除或锁定)。在这种情况下,潜在的更新器将等待第一个更新事务提交或回滚(如果它仍在进行中)。[...]如果第一个更新器提交,如果第一个更新器删除了该行,则第二个更新器将忽略该行,否则它将尝试将其操作应用于该行的更新版本。将重新计算命令的搜索条件(WHERE子句),以查看行的更新版本是否仍与搜索条件匹配。如果是,则第二更新器使用行的更新版本继续其操作。这种技术在PostgreSQL中的内部名称是“EvalPlanQual”。如果你想了解更多细节,我建议你阅读executor README中的相应部分。
Oracle这样做的方式看起来既费力又昂贵(重新计算整个语句),而PostgreSQL在重新计算那些已经更改的行时更有效。在缺点方面,PostgreSQL技术可能会导致令人惊讶的异常,如this article中所述。