I have a table like this in a Postgres database:
CREATE TABLE tabwithunique (
id SERIAL PRIMARY KEY,
key BIGINT NOT NULL UNIQUE,
value BIGINT NOT NULL
);
I want to design a statement that allows concurrent transactions to insert into this table without blocking on the unique constraint.
Instead, I would like "try-lock"-like behavior: I would like the insert to immediately return if a concurrent transaction is currently attempting to insert another row with the same key
.
I tried using ON CONFLICT DO NOTHING
, but it seems that Postgres still waits on concurrent transactions (so that it can return whether or not the insert succeeded):
Transaction 1 | Transaction 2 |
---|---|
BEGIN; |
|
BEGIN; |
|
INSERT INTO tabwithunique (key, value) VALUES (100, 111) ON CONFLICT DO NOTHING; → INSERT 0 1 |
|
INSERT INTO tabwithunique (key, values) VALUES (100, 222) ON CONFLICT DO NOTHING; (blocks) — this is what I DON'T want to happen. > I WANT this to immediately return INSERT 0 0. |
I want to avoid unnecessary blocking, and I would instead like the second insert to immediately return, indicating that the insert failed due to another row with the same key
, even though the other row is not yet committed. These transactions will be retried, so even if the other transactions ends up rolling-back, the row will eventually be inserted.
I'm running Postgres 13.9 with the default READ COMMITTED
transaction isolation level.
Ideally, I would like an answer that works when inserting many rows at the same time using a insert-query like INSERT INTO tabwithunique (SELECT ......