我正在尝试在PostgreSQL数据库中插入或更新数据。最简单的情况是键值配对(实际数据更复杂,但这是最小的明显例子)
设置值时,如果键不存在,我希望插入,否则更新。可悲的是Postgres没有插入或更新声明,所以我必须自己模仿它。
我一直在研究基本SELECT
密钥是否存在的想法,然后运行相应的INSERT
或UPDATE
。现在显然,这需要处于交易中,或者可能发生各种不良事件。
然而,这并不是我想要的方式 - 我明白可序列化交易存在限制,但我不知道如何解决这个问题。
情况如下 -
ab: => set transaction isolation level serializable;
a: => select count(1) from table where id=1; --> 0
b: => select count(1) from table where id=1; --> 0
a: => insert into table values(1); --> 1
b: => insert into table values(1); -->
ERROR: duplicate key value violates unique constraint "serial_test_pkey"
现在我希望它抛出通常的“由于并发更新而无法提交”,但我猜测因为插入不同的“行”这不会发生。
有一种简单的方法可以解决这个问题吗?
答案 0 :(得分:2)
在Postgres 9.1之前,存在隔离问题:
要求可序列化隔离仅保证单个MVCC快照将用于整个事务,这允许某些记录的异常。
也许你正在遇到这些“异常现象”。
检查行是否存在时,您可以尝试SELECT … FOR UPDATE。
或者,LOCK TABLE自己。
如果您正在尝试实施UPSERT,那么稍微更可靠(或者更不可靠)的方法是首先尝试UPDATE,检查受影响的行数,然后在没有更新行的情况下尝试INSERT。