Why is this Postgres query throwing “duplicate key value violates unique constraint”?
本问题已经有最佳答案,请猛点这里访问。
我实现了如下简单的更新/插入查询:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | -- NOTE: :time is replaced in real code, ids are placed statically for example purposes -- set status_id=1 to existing rows, update others UPDATE account_addresses SET status_id = 1, updated_at = :TIME WHERE account_id = 1 AND address_id IN (1,2,3) AND status_id IN (2); -- filter values according to what that update query returns, i.e. construct query like this to insert remaining new records: INSERT INTO account_addresses (account_id, address_id, status_id, created_at, updated_at) SELECT account_id, address_id, status_id, created_at::timestamptz, updated_at::timestamptz FROM (VALUES (1,1,1,:TIME,:TIME),(1,2,1,:TIME,:TIME)) AS sub(account_id, address_id, status_id, created_at, updated_at) WHERE NOT EXISTS ( SELECT 1 FROM account_addresses AS aa2 WHERE aa2.account_id = sub.account_id AND aa2.address_id = sub.address_id ) RETURNING id; -- throws: -- PG::UniqueViolation: ERROR: duplicate key value violates unique constraint"..." -- DETAIL: Key (account_id, address_id)=(1, 1) already exists. |
我这样做的原因是:记录可能存在于
这很好地工作,但同时进行,它会在竞态条件下在重复键上崩溃。但是,如果我试图原子性地"插入不存在的地方",为什么会出现种族状况呢?
啊。我只是多搜索了一点,插入不存在的地方不是原子的。
引自http://www.postgresql.org/message-id/[email protected]:
Mage writes:
The main question is that isn't"insert into ... select ... where not
exists" atomic?不,它不是:它会在存在其他事务时失败执行相同的操作,因为exists测试将只看到在命令启动之前提交。你可能会读到手册中关于并发性的章节:http://www.postgresql.org/docs/9.0/static/mvc.html
< /块引用>