I have the following (simplified) table examples in a PostgreSQL 11 database:
| Column | Type
| id | uuid
| core_id | character varying(255)
| name | character varying(255)
Indexes:
"examples_core_id_pkey" PRIMARY KEY, btree (core_id)
"examples_core_id_key" UNIQUE CONSTRAINT, btree (core_id)
"examples_id_unique" UNIQUE CONSTRAINT, btree (id)
Now, let's consider the following SQL statement:
INSERT INTO examples
( id, core_id, name)
VALUES
( $id, $coreId, $name)
ON CONFLICT (core_id)
DO UPDATE
SET
name = $name
When I try two inserts
- Insert 1 ('abc', 'abc', 'somename')
- Insert 2 ('abc' 'abc', 'somename')
I sometimes get a SequelizeUniqueConstraint error:
duplicate key value violates unique constraint
examples_id_unique
I don't understand why this is happening because I am specifying core_id in the ON CONFLICT clause. Thus, I am interpreting it so that if there's a lack of uniqueness on core_id, just perform the UPDATE. I was thinking postgres would just check the arbitrer index (core_id) in those cases and run the update.
Based on postgres docs v11
The optional ON CONFLICT clause specifies an alternative action to raising a unique violation or exclusion constraint violation error. For each individual row proposed for insertion, either the insertion proceeds, or, if an arbiter constraint or index specified by conflict_target is violated, the alternative conflict_action is taken.
I wonder if this is a concurrency problem because in a production environment, I get the following flow:
- Receive message 1 and message 2 with the same content at the same time.
- Message 1 passes, Message 2 fails with the sequelize validation error.
- Message 2 gets reprocessed, then passes.
This seems very similar to this question INSERT ON CONFLICT DO UPDATE SET (an UPSERT) statement with a unique constraint is generating constraint violations when run concurrently but haven't found a solution to this problem yet.
sequelizeversion 6.35.2". You are typically required to check if the queries you are running work without sequelize, otherwise that does not make it a minimal, reproducible example. Once you have checked, you can strip sequelize from your question or add the precision that query XXX works but not once executed from sequelize.DO UPDATE SET name = $namevery weird. Any reason why you don't use the special (and documented)excluded table, i.e.DO UPDATE SET name = Excluded.name?