Summary
test/recluster_extent.sh fails intermittently. The same commit passed and failed the same PG18 CI job in two different runs. The failing assertion is the one the suite exists to enforce, so this is either a real defect in the online-recluster extent mark or a race in the test itself. Which one is not yet established. This issue records the evidence; the conclusion will be added when it is proven, not before.
Evidence
CI, PG18, run 30772737889 (job 91562747530):
base 1500000 rows, 50000 inserted during the rewrite; sorted 1520000, appended 30000
FAIL the run does not claim rows written during the rewrite: got [no] want [yes]
The identical commit passed the identical job in run 30772271903. Both runs are of the tree merged as #339 / under review as #340. Non-determinism is therefore established as fact, independent of the cause.
Locally on PG18 the suite passes 8/8, with sorted ranging 400000-480000 across runs -- nowhere near the 1500000 threshold. The same suite also failed once on PG19 in an earlier local full-matrix run and passed on the rerun. So it has now been seen failing on two different majors and passing on both.
What the numbers rule out
The concurrent INSERT is a single transaction of 50000 rows, so any single snapshot sees all of them or none. A partial split therefore needs explaining.
Forcing the insert to commit entirely before the rewrite starts was tested directly. It produces:
base 1500000 rows, 50000 inserted during the rewrite; sorted 1550000, appended 0
That is all-or-nothing, and it is not what CI showed. So "the insert simply landed before the rewrite snapshotted" does not by itself account for the observed 1520000 / 30000.
The fixture uses stripe_row_limit => 20000, so a 50000-row insert produces groups of roughly 20000 / 20000 / 10000. A 20000 / 30000 split is consistent with exactly one of those groups falling at or below the mark. That is the specific failure mode record_online_sorted_extent was written to prevent, which is why this is not being written off as flakiness.
What is already proven about the test
The suite's premise check is:
check "the insert committed while the rewrite was still running" \
"$( [ "$INS_DONE" -lt "$RECL_DONE" ] && echo yes || echo no )" "yes"
This only establishes that the insert finished before the rewrite finished. It does not establish that the insert landed after the rewrite snapshotted its work set. Demonstrated by construction: with the insert forced to commit entirely before the rewrite starts, this premise check still PASSES while the property check fails. So the premise is too weak in at least one direction, regardless of what else is wrong.
That is a defect in the test independent of the outcome of the investigation, and it should be fixed either way.
The code under suspicion
src/columnar_vacuum.c :: record_online_sorted_extent. Its contract is that sort_status reads the mark as "every group numbered at or below this one is ordered". Its guard is that the rewrite's own reserved stripe ids must be consecutive from its lowest and the lowest live group must equal that lowest id; otherwise it marks less, or nothing. The stated justification is that a foreign reservation always consumes an id and therefore always leaves a gap in the rewrite's own ids.
The open question is whether that argument is airtight, specifically:
- whether ids are always drawn from one monotonic sequence, and whether a reserved-then-aborted id can leave a gap that is not foreign;
- whether
sort_status counts rows in all live groups at or below the mark regardless of who wrote them, or only the rewrite's own;
- whether a group can be invisible to the
lowestLive check yet later become visible at an id below the mark.
Not caused by column projection (#338)
The suite and the extent marking both predate #338, and the projection change does not touch the recluster path (columnar_vacuum.c passes a NULL projection, so it keeps the whole-group read). The failure surfaced on a #338 review PR only because that PR triggered a fresh CI run of an already-merged tree. This should still be confirmed rather than assumed.
Why this matters even if the product is correct
A gate that reds intermittently teaches its readers to ignore reds. This one has now produced a false-looking red on two majors. Whatever the cause, the test must end up either deterministic or honestly reporting an unmet premise instead of a failed property.
Summary
test/recluster_extent.shfails intermittently. The same commit passed and failed the same PG18 CI job in two different runs. The failing assertion is the one the suite exists to enforce, so this is either a real defect in the online-recluster extent mark or a race in the test itself. Which one is not yet established. This issue records the evidence; the conclusion will be added when it is proven, not before.Evidence
CI, PG18, run
30772737889(job 91562747530):The identical commit passed the identical job in run
30772271903. Both runs are of the tree merged as #339 / under review as #340. Non-determinism is therefore established as fact, independent of the cause.Locally on PG18 the suite passes 8/8, with
sortedranging 400000-480000 across runs -- nowhere near the 1500000 threshold. The same suite also failed once on PG19 in an earlier local full-matrix run and passed on the rerun. So it has now been seen failing on two different majors and passing on both.What the numbers rule out
The concurrent INSERT is a single transaction of 50000 rows, so any single snapshot sees all of them or none. A partial split therefore needs explaining.
Forcing the insert to commit entirely before the rewrite starts was tested directly. It produces:
That is all-or-nothing, and it is not what CI showed. So "the insert simply landed before the rewrite snapshotted" does not by itself account for the observed 1520000 / 30000.
The fixture uses
stripe_row_limit => 20000, so a 50000-row insert produces groups of roughly 20000 / 20000 / 10000. A 20000 / 30000 split is consistent with exactly one of those groups falling at or below the mark. That is the specific failure moderecord_online_sorted_extentwas written to prevent, which is why this is not being written off as flakiness.What is already proven about the test
The suite's premise check is:
This only establishes that the insert finished before the rewrite finished. It does not establish that the insert landed after the rewrite snapshotted its work set. Demonstrated by construction: with the insert forced to commit entirely before the rewrite starts, this premise check still PASSES while the property check fails. So the premise is too weak in at least one direction, regardless of what else is wrong.
That is a defect in the test independent of the outcome of the investigation, and it should be fixed either way.
The code under suspicion
src/columnar_vacuum.c :: record_online_sorted_extent. Its contract is thatsort_statusreads the mark as "every group numbered at or below this one is ordered". Its guard is that the rewrite's own reserved stripe ids must be consecutive from its lowest and the lowest live group must equal that lowest id; otherwise it marks less, or nothing. The stated justification is that a foreign reservation always consumes an id and therefore always leaves a gap in the rewrite's own ids.The open question is whether that argument is airtight, specifically:
sort_statuscounts rows in all live groups at or below the mark regardless of who wrote them, or only the rewrite's own;lowestLivecheck yet later become visible at an id below the mark.Not caused by column projection (#338)
The suite and the extent marking both predate #338, and the projection change does not touch the recluster path (
columnar_vacuum.cpasses a NULL projection, so it keeps the whole-group read). The failure surfaced on a #338 review PR only because that PR triggered a fresh CI run of an already-merged tree. This should still be confirmed rather than assumed.Why this matters even if the product is correct
A gate that reds intermittently teaches its readers to ignore reds. This one has now produced a false-looking red on two majors. Whatever the cause, the test must end up either deterministic or honestly reporting an unmet premise instead of a failed property.