Re: Test instability when pg_dump orders by OID
Noah Misch <noah@leadboat.com>
Commits
GET /api/v1/messages/:b64id/commits
the thread's linked commits as JSON, with link sources.
API reference →
-
Rewrite previous commit's test for TestUpgradeXversion compatibility.
- fb75e1ef7212 13.23 landed
- 22c6a44f01fd 14.20 landed
- 090c9c9608b3 15.15 landed
- c6dca7c3dd65 18.0 landed
- 49a09c6c51c0 17.7 landed
- 412d29fd2166 16.11 landed
- ad4412480d3f 19 (unreleased) landed
-
Sort DO_DEFAULT_ACL dump objects independent of OIDs.
- 4948bb9df421 14.20 landed
- 05341b2e9914 13.23 landed
- fbf967e996dd 15.15 landed
- e8d22095e5df 17.7 landed
- e68fa9a830f0 16.11 landed
- 7652142f4c14 18.0 landed
- b61a5c4bed7d 19 (unreleased) landed
-
Remove, from stable branches, the new assertion of no pg_dump OID sort.
- bc05590c7fcd 13.22 landed
- 7846f470964c 14.19 landed
- 70637d7ae0a2 15.14 landed
- 28e7252e450a 17.6 landed
- 216683296101 16.10 landed
- 0d2734eac345 18.0 landed
-
Sort dump objects independent of OIDs, for the 7 holdout object types.
- 04bc2c42f765 13.22 landed
- 7ee7c1cd389e 14.19 landed
- 22f126da6cce 15.14 landed
- 1ca1889ea6a3 17.6 landed
- 0ac1581c3f2d 16.10 landed
- c0ae03384fa3 18.0 landed
- 0decd5e89db9 19 (unreleased) landed
-
pg_dump: provide a stable sort order for rules.
- cc9a62c51a18 13.22 landed
- 25388fb2cb84 14.19 landed
- e99010cbd8e2 15.14 landed
- 9affed26349a 16.10 landed
- 5dd4957b28df 17.6 landed
-
pg_dump: include comments on not-null constraints on domains, too
- da71717f0a7c 19 (unreleased) cited
-
Verify roundtrip dump/restore of regression database
- 172259afb563 18.0 cited
-
In pg_dump, use simplehash.h to look up dumpable objects by OID.
- 92316a4582a5 15.0 cited
-
Tweak pg_dumpall to add GRANT CONNECT ON DATABASE ... TO PUBLIC when dumping
- 2ee56b6a3ab8 8.3.0 cited
-
Restructure operator classes to allow improved handling of cross-data-type
- a78fcfb51243 8.3.0 cited
-
First phase of project to use fixed OIDs for all system catalogs and
- 7c13781ee7a6 8.1.0 cited
-
Tweak pg_dump to say GRANT ALL when appropriate, rather than enumerating
- 1b68bcfad33e 7.2.1 cited
On Thu, Jul 17, 2025 at 09:24:02AM -0400, Robert Haas wrote:
> On Mon, Jul 7, 2025 at 3:27 PM Noah Misch <noah@leadboat.com> wrote:
> > Let's get rid of pg_dump's need to sort by OID, apart from catalog corruption
> > scenarios.
>
> +1. I had at one point believed that sorting by OID was a good way to
> make dumps stable, but this disproves that theory. Sorting by logical
> properties of the object is better.
Sorting by OID was a reasonable approximation, for its time.
> > Adding an assert found a total of seven affected object types.
> > See the second attached patch. The drawback is storing five more fields in
> > pg_dump memory: oprleft, oprright, opcmethod, opfmethod, and collencoding.
> > That seems minor relative to existing pg_dump memory efficiency. Since this
> > is a source of test flakes in v18, I'd like to back-patch to v18. I'm not
> > sure why the buildfarm hasn't seen the above diff, but I expect the diff could
> > happen there. This is another nice win for the new test from commit
> > 172259afb563d35001410dc6daad78b250924038. The order instability was always
> > bad for users, but the test brought it to the forefront. One might argue for
> > back-patching $SUBJECT further, too.
>
> I agree with back-patching it at least as far as v18. I think it
> probably wouldn't hurt anything to back-patch further, and it might
> avoid future buildfarm failures. Against that, there's a remote
> possibility that someone who is currently saving pg_dump output for
> later comparison, say in a case where OIDs are always stable in
> practice, could be displeased to see the pg_dump order change in a
> minor release. But that seems like a very weak argument against
> back-patching. I can't see us ever deciding to put up with buildfarm
> instability on such grounds.
Thanks for reviewing. I agree with those merits of back-patching further. A
back-patch to v13 has no pg_dump_sort.c conflicts, while pg_dump.c has
mechanical conflicts around retrieving the extra sort inputs. If there are no
objections in the next 72h, I'll likely back-patch.
> Reviewing:
>
> + * Sort by name. This differs from "Name:" in plain format output, which
> + * is a _tocEntry.tag. For example, DumpableObject.name of a constraint
> + * is pg_constraint.conname, but _tocEntry.tag of a constraint is relname
> + * and conname joined with a space.
>
> This comment is useful, but if I were to be critical, it does a better
> job saying what this field isn't than what it is.
True. I've changed it to this:
* Sort by name. With a few exceptions, names here are single catalog
* columns. To get a fuller picture, grep pg_dump.c for "dobj.name = ".
* Names here don't match "Name:" in plain format output, which is a
* _tocEntry.tag. For example, DumpableObject.name of a constraint is
* pg_constraint.conname, but _tocEntry.tag of a constraint is relname and
* conname joined with a space.
The patch's original change to the comment was a reaction to my own surprise.
Reading "pg_dump regression|grep Name:|sort|grep CONSTRAINT" I saw unique
"Name:" output for constraints, which felt at odds with the instability in
DOTypeNameCompare() sorting them. But it wasn't the name I was looking for:
- getConstraints() sets DumpableObject.name = conname
- DOTypeNameCompare() sorts by DumpableObject.name
- dumpConstraint() sets _tocEntry.tag = "relname conname"
- _tocEntry.tag becomes the "Name:" in pg_dump output
Long-term, in a post-scarcity world, I'd do one of these or similar:
a. Change what we store in DumpableObject.name so it matches _tocEntry.tag.
b. Rename field DumpableObject.name, so there's no longer a field called
"name" with contents different from the "Name:" values in pg_dump output.
> + * Sort by encoding, per pg_collation_name_enc_nsp_index. This is
> + * mostly academic, because CREATE COLLATION has restrictions to make
> + * (nspname, collname) uniquely identify a collation within a given
> + * DatabaseEncoding. pg_import_system_collations() bypasses those
> + * restrictions, but pg_dump+restore fails after a
> + * pg_import_system_collations('my_schema') that creates collations
> + * for a blend of encodings.
>
> This comment is also useful, but if I were to be critical again, it
> does a better job saying why we shouldn't do what the code then does
> than why we should.
I've tried the following further refinement. If it's worse, I can go back to
the last version.
diff --git a/src/bin/pg_dump/pg_dump_sort.c b/src/bin/pg_dump/pg_dump_sort.c
index ffae7b3..f7d6a03 100644
--- a/src/bin/pg_dump/pg_dump_sort.c
+++ b/src/bin/pg_dump/pg_dump_sort.c
@@ -248,7 +250,19 @@ DOTypeNameCompare(const void *p1, const void *p2)
if (cmpval != 0)
return cmpval;
- /* To have a stable sort order, break ties for some object types */
+ /*
+ * To have a stable sort order, break ties for some object types. Most
+ * catalogs have a natural key, e.g. pg_proc_proname_args_nsp_index.
+ * Where the above "namespace" and "name" comparisons don't cover all
+ * natural key columns, compare the rest here.
+ *
+ * The natural key usually refers to other catalogs by surrogate keys.
+ * Hence, this translates each of those references to the natural key of
+ * the referenced catalog. That may descend through multiple levels of
+ * catalog references. For example, to sort by pg_proc.proargtypes,
+ * descend to each pg_type and then further to its pg_namespace, for an
+ * overall sort by (nspname, typname).
+ */
if (obj1->objType == DO_FUNC || obj1->objType == DO_AGG)
{
FuncInfo *fobj1 = *(FuncInfo *const *) p1;
@@ -312,13 +326,16 @@ DOTypeNameCompare(const void *p1, const void *p2)
CollInfo *cobj2 = *(CollInfo *const *) p2;
/*
- * Sort by encoding, per pg_collation_name_enc_nsp_index. This is
- * mostly academic, because CREATE COLLATION has restrictions to make
- * (nspname, collname) uniquely identify a collation within a given
- * DatabaseEncoding. pg_import_system_collations() bypasses those
- * restrictions, but pg_dump+restore fails after a
- * pg_import_system_collations('my_schema') that creates collations
- * for a blend of encodings.
+ * Sort by encoding, per pg_collation_name_enc_nsp_index. Wherever
+ * this changes dump order, restoring the dump fails anyway. CREATE
+ * COLLATION can't create a tie for this to break, because it imposes
+ * restrictions to make (nspname, collname) uniquely identify a
+ * collation within a given DatabaseEncoding. While
+ * pg_import_system_collations() can create a tie, pg_dump+restore
+ * fails after pg_import_system_collations('my_schema') does so.
+ * There's little to gain by ignoring one natural key column on the
+ * basis of those limitations elsewhere, so respect the full natural
+ * key like we do for other object types.
*/
cmpval = cobj1->collencoding - cobj2->collencoding;
if (cmpval != 0)