Hi,
On 12/20/22 10:41 PM, Robert Haas wrote:
On Tue, Dec 20, 2022 at 3:39 PM Robert Haas <robertmh...@gmail.com> wrote:
I think this might be the only WAL record type where there's a
problem, but I haven't fully confirmed that yet.
It's not. GIST has the same issue. The same test case demonstrates the
problem there, if you substitute this test script for
kpt_hash_setup.sql and possibly also run it for somewhat longer. One
might think that this wouldn't be a problem, because the comments for
gistxlogDelete say this:
/*
* In payload of blk 0 : todelete OffsetNumbers
*/
But it's not in the payload of blk 0. It follows the main payload.
Oh right, nice catch!
Indeed, we can see in gistRedoDeleteRecord():
"
todelete = (OffsetNumber *) ((char *) xldata + SizeOfGistxlogDelete);
"
This is the reverse of xl_heap_freeze_page, which claims that freeze
plans and offset numbers follow, but they don't: they're in the data
for block 0.
oh right, we can see in heap_xlog_freeze_page():
"
plans = (xl_heap_freeze_plan *) XLogRecGetBlockData(record, 0,
NULL);
offsets = (OffsetNumber *) ((char *) plans +
(xlrec->nplans *
sizeof(xl_heap_freeze_plan)));
"
xl_btree_delete is also wrong, claiming that the data
follows when it's really attached to block 0.
oh right, we can see in btree_xlog_delete():
"
char *ptr = XLogRecGetBlockData(record, 0, NULL);
page = (Page) BufferGetPage(buffer);
if (xlrec->nupdated > 0)
{
OffsetNumber *updatedoffsets;
xl_btree_update *updates;
updatedoffsets = (OffsetNumber *)
(ptr + xlrec->ndeleted * sizeof(OffsetNumber));
updates = (xl_btree_update *) ((char *) updatedoffsets +
xlrec->nupdated *
sizeof(OffsetNumber));
"
I guess whatever else we
do here, we should fix the comments.
Agree, please find attached a patch proposal doing so.
Bottom line is that I think the two cases that have alignment issues
as coded are xl_hash_vacuum_one_page and gistxlogDelete. Everything
else is OK, as far as I can tell right now.
Thanks a lot for the repro(s) and explanations! That's very useful/helpful.
Based on your discovery about the wrong comments above, I'm now tempted to fix
those 2 alignment issues
by using a FLEXIBLE_ARRAY_MEMBER within those structs (as you proposed in [1])
(as that should also prevent
any possible wrong comments about where the array is located).
What do you think?
[1]:
https://www.postgresql.org/message-id/CA%2BTgmoaVcu_mbxbH%3DEccvKG6u8%2BMdQf9zx98uAL9zsStFwrYsQ%40mail.gmail.com
Regards,
--
Bertrand Drouvot
PostgreSQL Contributors Team
RDS Open Source Databases
Amazon Web Services: https://aws.amazon.com
diff --git a/src/include/access/gistxlog.h b/src/include/access/gistxlog.h
index 33f1c7e31b..95068feb87 100644
--- a/src/include/access/gistxlog.h
+++ b/src/include/access/gistxlog.h
@@ -52,9 +52,7 @@ typedef struct gistxlogDelete
TransactionId snapshotConflictHorizon;
uint16 ntodelete; /* number of deleted offsets */
- /*
- * In payload of blk 0 : todelete OffsetNumbers
- */
+ /* TODELETE OFFSET NUMBER ARRAY FOLLOWS */
} gistxlogDelete;
#define SizeOfGistxlogDelete (offsetof(gistxlogDelete, ntodelete) +
sizeof(uint16))
diff --git a/src/include/access/heapam_xlog.h b/src/include/access/heapam_xlog.h
index 5c77290eec..1117e95ede 100644
--- a/src/include/access/heapam_xlog.h
+++ b/src/include/access/heapam_xlog.h
@@ -345,8 +345,9 @@ typedef struct xl_heap_freeze_page
TransactionId snapshotConflictHorizon;
uint16 nplans;
- /* FREEZE PLANS FOLLOW */
- /* OFFSET NUMBER ARRAY FOLLOWS */
+ /*
+ * In payload of blk 0 : FREEZE PLANS and OFFSET NUMBER ARRAY
+ */
} xl_heap_freeze_page;
#define SizeOfHeapFreezePage (offsetof(xl_heap_freeze_page, nplans) +
sizeof(uint16))
diff --git a/src/include/access/nbtxlog.h b/src/include/access/nbtxlog.h
index 3b2d959c69..1aa8e7eca5 100644
--- a/src/include/access/nbtxlog.h
+++ b/src/include/access/nbtxlog.h
@@ -236,9 +236,12 @@ typedef struct xl_btree_delete
uint16 ndeleted;
uint16 nupdated;
- /* DELETED TARGET OFFSET NUMBERS FOLLOW */
- /* UPDATED TARGET OFFSET NUMBERS FOLLOW */
- /* UPDATED TUPLES METADATA (xl_btree_update) ARRAY FOLLOWS */
+ /*
+ * In payload of blk 0 :
+ * - DELETED TARGET OFFSET NUMBERS
+ * - UPDATED TARGET OFFSET NUMBERS
+ * - UPDATED TUPLES METADATA (xl_btree_update) ARRAY
+ */
} xl_btree_delete;
#define SizeOfBtreeDelete (offsetof(xl_btree_delete, nupdated) +
sizeof(uint16))