db: recorders of result_latest still deadlock under a burst of verdicts (12 in ten minutes, 2026-11-12 22:25Z) #51

Open
opened 2026-11-12 22:42:55 +00:00 by xemmerling · 0 comments
Owner

Seen on t.tilo.so (86fa55c0) on 2026-11-12: PostgreSQL ended 12 transactions for a deadlock between 22:25:37Z and 22:30Z, none in the two hours before. In those ten minutes 4,128 checks were told to CI heads. The server logged twice driven again once: recording a verdict: db error: ERROR: deadlock detected (22:29:35Z, 22:37:35Z); no check was told an error for it this time.

The statements, from the database's log, both in Db::record_in (src/db/results.rs):

  • SELECT trust, run FROM result_latest WHERE key = $1 FOR UPDATE
  • INSERT INTO result_latest (key, trust, ...) VALUES (...) ON CONFLICT (key, trust) DO UPDATE SET ...

Shapes: two processes each waiting for the other's transaction, one in the SELECT and one in the INSERT; and rings of three to five processes waiting on tuples of result_latest and on each other's transactions ("while locking tuple (63282,1) in relation result_latest").

72849b76 made a batch record its keys in their order (record_many), which ended the deadlock of 2026-11-07 between two batches. What still deadlocks is not yet named. To test, not to assume: a transaction that records more than one batch, or a batch and single records, so its keys are not in one order over the whole transaction; the other writers of the table that do not go through record_many (src/ci/bisect.rs, src/db/measure.rs); and the order in which FOR UPDATE takes the rows of one key that has several trusts while another recorder inserts a new trust's row for it.

Wanted: every writer of result_latest takes its locks in one order for the whole transaction, shown by a test with two recorders that deadlocks today. No retry over it.

Seen on t.tilo.so (86fa55c0) on 2026-11-12: PostgreSQL ended 12 transactions for a deadlock between 22:25:37Z and 22:30Z, none in the two hours before. In those ten minutes 4,128 checks were told to CI heads. The server logged twice `driven again once: recording a verdict: db error: ERROR: deadlock detected` (22:29:35Z, 22:37:35Z); no check was told an error for it this time. The statements, from the database's log, both in `Db::record_in` (`src/db/results.rs`): - `SELECT trust, run FROM result_latest WHERE key = $1 FOR UPDATE` - `INSERT INTO result_latest (key, trust, ...) VALUES (...) ON CONFLICT (key, trust) DO UPDATE SET ...` Shapes: two processes each waiting for the other's transaction, one in the SELECT and one in the INSERT; and rings of three to five processes waiting on tuples of `result_latest` and on each other's transactions ("while locking tuple (63282,1) in relation result_latest"). 72849b76 made a batch record its keys in their order (`record_many`), which ended the deadlock of 2026-11-07 between two batches. What still deadlocks is not yet named. To test, not to assume: a transaction that records more than one batch, or a batch and single records, so its keys are not in one order over the whole transaction; the other writers of the table that do not go through `record_many` (`src/ci/bisect.rs`, `src/db/measure.rs`); and the order in which `FOR UPDATE` takes the rows of one key that has several trusts while another recorder inserts a new trust's row for it. Wanted: every writer of `result_latest` takes its locks in one order for the whole transaction, shown by a test with two recorders that deadlocks today. No retry over it.
Sign in to join this conversation.
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
tilo/t#51
No description provided.