PostgreSql upsert:哪种显式锁定方法?

时间:2014-02-06 22:42:34

标签: locking postgresql-9.2 upsert

从这个question开始,我想使用以下方法在PostGreSql表中执行upsert:

UPDATE table SET field='C', field2='Z' WHERE id=3;
INSERT INTO table (id, field, field2)
   SELECT 3, 'C', 'Z'
   WHERE NOT EXISTS (SELECT 1 FROM table WHERE id=3);

我知道我必须在事务中执行它并且我应该使用显式锁定方法。我一直在阅读postgresql文档,但我仍然在三种类型的锁之间犹豫不决(每种锁的区别对我来说都不是很清楚):

ROW EXCLUSIVE
SHARE ROW EXCLUSIVE
EXCLUSIVE

我想避免重试交易。我并不期望在行上有太多的并发性,尽管这可能会不时发生。在极少数情况下,可能会同时尝试删除和插入同一行。

1 个答案:

答案 0 :(得分:2)

您需要自包含锁定类型,排除所有DML命令

此操作的正确锁定类型为EXCLUSIVE。它与所有其他锁冲突,包括其自身, ACCESS SHARE

{p> ACCESS SHARESELECT拍摄。所有其他命令需要更高的锁定级别。因此,您的upsert事务将阻止除SELECT之外的所有内容,这就是您想要的内容。

请参阅the docs on explicit locking

所以:

BEGIN;
LOCK TABLE ... IN EXCLUSIVE MODE;
...

(使用单词ROW对某些表级锁定进行历史记录和可怕的命名并不能简化对PostgreSQL锁类型的理解。

顺便说一下,您的应用程序应该检查从UPDATE返回的行数。如果它不为零,则可以跳过INSERT