I need suggestions/ideas of handling a issue with deadlocks. I'm having multiple batch inserts commands to same table:
insert into ip (id, p_id, m_type, m_id, sha256, path) VALUES (1,ドル 2,ドル 3,ドル 4,ドル 5,ドル 6,ドル7,ドル8ドル), (9,ドル 10,ドル 11,ドル 12,ドル 13,ドル 14,ドル 15,ドル 16ドル), (17,ドル 18,ドル 19,ドル 20,ドル 21,ドル 22,ドル 23,ドル 24ドル), (25,ドル 26,ドル 27,ドル 28,ドル 29,ドル 30,ドル 31ドル ,32ドル), (33,ドル 34,ドル 35,ドル 36,ドル 37,ドル 38,ドル39,540ドル), (41,ドル 42,ドル 43,ドル44,545,ドル 46,ドル 47,ドル48ドル) ... ON CONFLICT DO NOTHING
And since Insertion order is not honored in database most probably because PostgreSQL is launching several parallel insert threads, I'm getting the following deadlocks:
[1111]:ERROR:deadlock detected
[1111]:DETAIL: Process 1111 waits for ShareLock on transaction 1423145219; blocked by process 2222.
Process 1111 waits for ShareLock on transaction 1423145222: blocked by process 1111.
Process 1111: insert into ip (id, p_id, m_type, m_id, sha256, path) VALUES (1,ドル 2,ドル 3,ドル 4,ドル 5,ドル 6,ドル7,ドル8ドル), (9,ドル 10,ドル 11,ドル 12,ドル 13,ドル 14,ドル 15,ドル 16ドル), (17,ドル 18,ドル 19,ドル 20,ドル 21,ドル 22,ドル 23,ドル 24ドル), (25,ドル 26,ドル 27,ドル 28,ドル 29,ドル 30,ドル 31ドル ,32ドル), (33,ドル 34,ドル 35,ドル 36,ドル 37,ドル 38,ドル39,540ドル), (41,ドル 42,ドル 43,ドル44,545,ドル 46,ドル 47,ドル48ドル) ... ON CONFLICT DO NOTHING
Process 2222: insert into ip (id, p_id, m_type, m_id, sha256, path) VALUES (1,ドル 2,ドル 3,ドル 4,ドル 5,ドル 6,ドル7,ドル8ドル), (9,ドル 10,ドル 11,ドル 12,ドル 13,ドル 14,ドル 15,ドル 16ドル), (17,ドル 18,ドル 19,ドル 20,ドル 21,ドル 22,ドル 23,ドル 24ドル), (25,ドル 26,ドル 27,ドル 28,ドル 29,ドル 30,ドル 31ドル ,32ドル), (33,ドル 34,ドル 35,ドル 36,ドル 37,ドル 38,ドル39,540ドル), (41,ドル 42,ドル 43,ドル44,545,ドル 46,ドル 47,ドル48ドル) ... ON CONFLICT DO NOTHING
As we can see the bulk inserts acquire ShareLocks which deadlock each other.
On the one hand I don't want to acquire an exclusive lock for each bulk insert on the entire table because I guess it will affect the parallel inserts performance.
On the other hand I'm not 100% sure that enforcing order (by id column which is a PK with a CTE select) is a good solution, because even if I could guarantee insertion order that would NOT ensure a later select statement would return them in that order since it's multiple bulk insertions, and the order might change.
(And also I have to reorder the table for each bulk insert).
-
What does 'a later select statement' have to do with your current predicament?jjanes– jjanes2023年09月03日 19:27:04 +00:00Commented Sep 3, 2023 at 19:27
1 Answer 1
The best solution would be to make sure that no two of the concurrent statements try to insert rows with the same primary or unique key. And no, ON CONFLICT
doesn't do that trick.
The second best solution is to sort the rows inserted by a single statement before inserting them:
WITH r (id, p_id, m_type, m_id, sha256, path) AS
(
VALUES
(1,ドル 2,ドル 3,ドル 4,ドル 5,ドル 6,ドル 7,ドル 8ドル),
(9,ドル 10,ドル 11,ドル 12,ドル 13,ドル 14,ドル 15,ドル 16ドル),
...
)
INSERT INTO ip (id, p_id, m_type, m_id, sha256, path)
SELECT * FROM r
ORDER BY r.id;
That should only cause live locks, but no deadlocks.
Of course there are other causes for deadlocks like triggers, but you didn't mention any such details.
Explore related questions
See similar questions with these tags.