Repository navigation
The Fleet page and the fleet overview total PostgreSQL deadlocks without ordering databases whose counter never moved (#5526) - #5536
Merged
Conversation
…t in one window over the whole fleet (#5526)
erikdarlingdata
marked this pull request as ready for review
October 8, 2026 05:16
…ount the rest from one unordered aggregate (#5526)
…aims in its comments (#5526)
…not a 30-day rig label
This was referenced Oct 8, 2026
Closed
erikdarlingdata
added a commit
that referenced
this pull request
Oct 8, 2026
The version goes from 3.9.0 to 3.10.0. In the CHANGELOG, the entries for PRs merged since 3.9.0, through #5536, are spliced into a new [3.10.0] - 2026-10-08 section. Entries that belong together are folded, so the section holds 257 entries. The prose moves to docs/changelog/3.10.md, and the archive census gains its row. An Important entry covers the Darling store migrations V158 through V170, which run on the service's first start. None of them rewrites a large table or needs an offline window. The upgrade-path test also gets its fixture for the 3.9.0 release, migration-ladder-v3.9.0.sql, generated from the v3.9.0 tag. Release checklist steps 1, 2, 2a and 4 for 3.10.0.
8 of 9 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #5526
What changed and why
The Fleet page totals and the
get_fleet_overviewtool count PostgreSQL deadlocks as counter differences overcollect.pg_database_stats:deadlocks - LAG(deadlocks) OVER (PARTITION BY server_id, database_name ORDER BY collection_time). That sorts and windows every row of the window. On the field store (#5508, batch 4 item 2) the first version of this PR, which differenced one server at a time, was only 2.7% faster over 30 days (26,575 ms against 27,319 ms cold), because both forms spend the time sorting and windowing all 17.1 M rows. This version stops ordering rows that cannot matter.Most
(server_id, database_name)pairs never change their counter inside a window. For such a pair every difference is 0, so ordering it buys nothing.(server_id, database_name): row count,count(deadlocks),min,max.count(deadlocks) = count(*)(a counter in every row) andmin = max. A flat pair ofnsamples hasn - 1differences, all 0. It adds 0 tocnt, nothing tolast_seenandn - 1tointervals. That is exact, not an approximation.LAG, unchanged, one server at a time. The read is bounded byserver_id(the hypertable's segmentby,server_idonly, default ordercollection_time DESC) so a compressed chunk is read through its segment index, and keeps that server's non-flat pairs by name. The NULL-named shared-relation series is matched byIS NULL, because= ANYnever matches NULL. A server with no non-flat pair skips the ordered read (a one-time filter in the plan).cnt0,last_seenNULL,intervals= the sum ofn - 1. A server whose only row in the window is one sample still getsintervals0. A server with no row in the window still does not appear. Output columns, types and row set equal the old read for every input.ViewerDataService.FleetTotalsSql) returns only the total, so it keeps the pairs withmin(deadlocks) <> max(deadlocks)and needs no "counter in every row" half: a pair that never takes two values adds nothing to the sum of positive differences, NULLs included. The two reads are different SQL in different projects, so they stay two constants; their comments point at each other.Files:
DarlingFleetReader.cs(FleetPgDeadlockSql),ViewerDataService.Fleet.cs(FleetTotalsSql), and tests.Measurements
The 30-day window below is a measurement window only. No caller can ask for it: the fleet overview tool caps
hours_backat 168, the web/api/fleetclamps to 1..168, and the viewer totals read has one caller that always passes 1 hour. The changelog entry and the source comments say so.Field store (from the issue and #5508 comment 6053411189, batch 4 item 2; 50 targets, 17.1 M rows, 31 chunks, 29 decompressed): old form 26,854 ms cold and 26,571 ms warm over 30 days. The first version of this PR (per-server lateral): 26,575 ms against 27,319 ms cold, 2.7% faster. Not yet measured on the large store for this version; read-only SQL for it (old against new over 30 days, with a same-rows check) is written and ready to run there.
Rig numbers (not the large store). PostgreSQL 18.6, TimescaleDB 2.30.1, UTC, default work_mem, no parallel workers used. Built through the real migrate, then the shipped hypertable and compression settings (1-day chunks,
segmentby = server_id). 5.22 M rows over 30.5 days at one row a minute, 20 servers plus 3 small ones, 123 pairs in the window, 32 chunks (30 compressed, 2 not). Two seeds: "5%" (9 of 123 pairs not flat: about 5% moving, plus a counter reset, a partially-NULL pair, an all-NULL pair, a single-row pair, pairs that appear mid-window, a retried-write twin, a pair and a server entirely before the window) and "all changed" (every pair moves).EXPLAIN (ANALYZE, BUFFERS), warm, 30-day window:What to read from this, honestly:
cnton both seeds (159 and 2,604).Test plan
FleetPgDeadlockFlatPairLiveTests(renamed from the first version's file): runs the previous query text (kept as a literal) and the shippedFleetPgDeadlockSqlandFleetTotalsSqlon one seed, whole result row by row, plus hand-worked numbers for servers with only flat pairs, NULL counters (a constant with one NULL, an all-NULL pair, NULL then moving), a moving NULL-named series, the counter reset, the one-row server, the retried-write twin and a server outside the window. Then two generated seeds (about 9,000 rows each: mixed, and every pair moving) get the same comparison.count(deadlocks) = count(*)from the service read fails the live test (server with NULL counters: 6 intervals against 4); dropping theIS NULLbranch fails it (the moving NULL-named series gives count 0 against 3); inverting the Fleet pageHAVINGfails it (total 0 against 19).DarlingFleetDeadlockCoverageTestsandViewerFleetRollupSqlTests(the flat rule,n - 1, one window function, per-server filter, name and NULL-name match, both window bounds twice in both reads).*FleetPgDeadlockFlatPair*,*DarlingFleetReader*,*DarlingFleetDeadlockCoverage*,*DarlingFleetDto*,*DarlingMcpFleetTools*,*ViewerFleet*,*FleetReadsAreBounded*,*FleetCardPostgresCpu*: 194 run, 0 failed.*Census*,*Ratchet*,*Hygiene*,*Pin*,*RepoFileAdoption*,*FleetIdentifierScrub*,*RegisteredServerSettingDrift*,*TsqlConventionGuard*,*Guard*,*Scan*,*DocComment*,*CommandTimeout*: 1,985 run, 0 failed, 2 skipped. After mergingorigin/dev, rebuilt with 0 warnings and re-ran the fleet pins, Census, Hygiene and Ratchet: 637 run, 0 failed, 5 skipped (no live database running then).WHERE (cardinality(s.ordered_names) > 0 OR s.ordered_null_name)is now pinned inDarlingFleetDeadlockCoverageTests. RED-checked: with the line removed from the SQL the pin fails ("Not found"), restored, passes. Rebuilt with 0 warnings; then*DarlingFleet*,*DarlingMcpFleetTools*,*ViewerFleetRollup*,*Census*,*Ratchet*,*Hygiene*,*Pin*,*RepoFileAdoption*: 1,243 run, 0 failed, 35 skipped (live PostgreSQL classes, no database this round).Changelog
SECTION: Fixed
ENTRY:
REF:
[The Fleet page and the fleet overview total PostgreSQL deadlocks without ordering databases whose counter never moved (#5526) #5536]: The Fleet page and the fleet overview total PostgreSQL deadlocks without ordering databases whose counter never moved (#5526) #5536