We are using Postgres as part of our backend structure in Nodejs (Using pg). This is a very high multi process environment with a bunch of microservices, where the services query the same table. There is basically a column which functions as a lock 'status' - which value is either 'pending' for unlocked, or 'in-process' for locked.
There are two queries which select data from the table and lock the corresponding rows:
UPDATE market AS m
SET status='in_process', status_update_timestamp='${timestamp}'
WHERE m.guid IN
(SELECT guid FROM market
WHERE status = 'pending'
ORDER BY created_at
LIMIT 1 FOR UPDATE)
RETURNING *
UPDATE market AS m
SET status = 'in_process', status_update_timestamp = '${timestamp}'
WHERE m.guid IN
(SELECT guid FROM market
WHERE request_status='pending' AND asset_id IN (${myArray.join(",")})
FOR UPDATE)
RETURNING *
And one queries which unlocks rows based on guids:
UPDATE market
SET status='pending', status_update_timestamp='${timestamp}'
WHERE guid IN ('${guids.join("','")}')
There are cases where the two selecting queries can block each other, and also cases where the unlocking query and one other selecting query block eachother.
All of these queries can be executed in parallel from multiple services, and even though they are supposed to be atomic according to the documentation (link), we still get an error from postgres that 'deadlock is detected'. We tried wrapping the queries with BEGIN and END, different isolation levels, and different ORDER BYs but still without any improvement.
Is there any problem in the queries that give rise to deadlocks? Is this a problem that have to be solved in the application logic? Any help is welcome.
Table structure:
CREATE TABLE market
(
id BIGSERIAL not null constraint market_pkey primary key,
guid UUID DEFAULT uuid_generate_v4(),
asset_id BIGINT,
created_at TIMESTAMP DEFAULT current_timestamp,
status_update_timestamp TIMESTAMP DEFAULT current_timestamp,
status VARCHAR DEFAULT 'pending'
);