Postgres deadlocks on concurrent upserts Postgres deadlocks on concurrent upserts postgresql postgresql

Postgres deadlocks on concurrent upserts


I can think of three solutions:

  1. You insert only one row per statement, but that's inefficient.

  2. You sort the rows before inserting them.

  3. You retry a transaction if it gets a deadlock or serialization error.

I'd prefer the third solution unless the errors happen very often.


Your query's syntax allows ordering the values easily:

INSERT INTO documents          (version, source, source_id, ingestion_date)   SELECT * FROM (      VALUES          (0, 'googledrive', 'alpha', '2017-09-21T07:03:51.074Z'),          (0, 'googledrive', 'beta', '2017-09-21T07:03:51.074Z')          (0, 'googledrive', 'gamma', '2017-09-21T07:03:51.074Z'),          (0, 'googledrive', 'delta', '2017-09-21T07:03:51.074Z'),          (0, 'googledrive', 'epsilon', '2017-09-21T07:03:51.074Z'),          (0, 'googledrive', 'zeta', '2017-09-21T07:03:51.074Z')      ) AS v ORDER BY source, source_id      ON CONFLICT (source, source_id)

This should solve your problem. Performance should be nice, as the sort will be tiny.