Repository navigation
fix(core): scope and check the UNLOGGED state sync restore load - #592
Merged
Merged
Conversation
Restores set every table in `public` to UNLOGGED for the data load and back to LOGGED afterwards, logging and ignoring tables that failed to convert. Two problems followed: - The LOGGED pass ran alphabetically. sla_node_reports references sla_rollups and sorts first, and postgres will not make a table LOGGED while it references an UNLOGGED one, so every restore left sla_node_reports UNLOGGED. A table could also stay UNLOGGED for lack of disk: SET LOGGED rewrites the table and WAL-logs all of it, so it needs about twice the table's size free. - The entrypoint does not shut postgres down cleanly, and crash recovery empties UNLOGGED tables, so those tables lost their contents on every container stop. sla_node_reports feeds SLA rollup validation. With wal_level=replica the UNLOGGED load saved little or no WAL, because SET LOGGED writes the whole table to WAL anyway, and it added a full rewrite of every table, mediorum's included since they share the schema. Restores now leave persistence alone. After truncating, they convert any snapshot table an earlier restore left UNLOGGED while it is empty, and fail if that is not possible. At startup, before the node starts, small UNLOGGED tables in `public` are converted back automatically; larger ones are reported with the command to fix them. Conversion retries tables that reference still-unlogged ones, so order no longer matters. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
rickyrombo
added this pull request to stack #594
October 2, 2026 21:45
Removing the UNLOGGED data load risks bringing back the OOM kills during restore that #253 fixed, so keep it and fix how it fails instead: - Only the snapshot tables go UNLOGGED for the load, not all of `public`; mediorum's tables are no longer rewritten. - Both conversions retry tables whose references are not converted yet, so sla_node_reports no longer stays UNLOGGED. - Before converting back, the restore checks there is about twice the largest table free on postgres's data disk, and fails with the sizes if not. - The restore fails if any snapshot table is still UNLOGGED afterwards, instead of logging and continuing. The startup repair of tables earlier restores left UNLOGGED is unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Merged
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.
Summary
Keeps #253's approach of loading snapshot data into non-durable (
UNLOGGED) tables, and fixes how it fails. #253 fixed out-of-memory kills during restore, and this load may be what did it. Tables that earlier restores leftUNLOGGEDare repaired at startup.Why
Since #253, restores set every table in
publictoUNLOGGEDfor the data load, then back toLOGGED. Any table that failed to convert back was only logged as a warning, and the restore carried on.sla_node_reportsstayedUNLOGGEDafter every restore. TheLOGGEDpass ran in alphabetical order.sla_node_reportsreferencessla_rollupsand sorts first, and Postgres refuses to make a tableLOGGEDwhile it references anUNLOGGEDone (could not change table "sla_node_reports" to logged because it references unlogged table "sla_rollups", reproduced in the harness). This happened even with plenty of disk.UNLOGGEDfor lack of disk.SET LOGGEDrewrites the table and writes all of it to WAL, so it needs about twice the table's size free. An operator hit this withcore_transactions(~60 GB).UNLOGGEDtables get emptied. Crash recovery empties them, and the container entrypoint doesn't shut Postgres down cleanly, so every container stop wiped them.sla_node_reportsfeeds SLA rollup validation (isValidRollup), so an affected node disagrees with the network about rollups.uploads,blobs, …) sharepublic, so they were rewritten twice on every restore.The first version of this PR removed the
UNLOGGEDload entirely. Ray confirmed #253 fixed the out-of-memory kills he was seeing during restores. #253 changed several things at once and we can't tell which one fixed them, so this version keeps theUNLOGGEDload.Changes
UNLOGGEDfor the load. Mediorum's and the ETL's tables aren't touched.UNLOGGEDat all just loadsLOGGED, which is slower but safe, with a warning.SHOW data_directoryplusstatfs), and fails with the sizes if it isn't. If free space can't be read (for example, Postgres runs on another host), it logs a warning and converts anyway.UNLOGGED, and the error shows in the restore process status.UNLOGGEDtables inpublicup to 1 GiB are converted back automatically. Larger ones are logged as errors with the command to run and the disk it needs. Nothing here fails startup.Risks
RETRY. CometBFT then re-runs the restore, so on a too-small disk it loops until space is freed, instead of "succeeding" with tables that get wiped on the next stop. That's visible in logs and the process status, but it repeats a long restore each time.sla_node_reportsis small.Testing
TEST_DB_URL, run in the harness):LOGGEDandUNLOGGEDconversion of a parent/child pair in either order,pkg/core/serverpackage passes in the harness withTEST_DB_URLset.make test-unitpasses.Operators
Nodes that state-synced since #253 likely have
sla_node_reports, and possibly other tables,UNLOGGED:After upgrading, small tables are fixed at startup. Larger ones show up in the logs with instructions.
🤖 Generated with Claude Code