Skip to content

Commit f5e0ff4

Browse files
author
Amit Kapila
committed
Fix reorder buffer memory accounting for toast changes.
While processing toast changes in logical decoding, we rejigger the tuple change to point to in-memory toast tuples instead to on-disk toast tuples. And, to make sure the memory accounting is correct, we were subtracting the old change size and then after re-computing the new tuple, re-adding its size at the end. Now, if there is any error before we add the new size, we will release the changes and that will update the accounting info (subtracting the size from the counters). And we were underflowing there which leads to an assertion failure in assert enabled builds and wrong memory accounting in reorder buffer otherwise. Author: Bertrand Drouvot Reviewed-by: Amit Kapila Backpatch-through: 13, where memory accounting was introduced Discussion: https://postgr.es/m/92b0ee65-b8bd-e42d-c082-4f3f4bf12d34@amazon.com
1 parent cc057fb commit f5e0ff4

File tree

1 file changed

+23
-13
lines changed

1 file changed

+23
-13
lines changed

src/backend/replication/logical/reorderbuffer.c

Lines changed: 23 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -290,7 +290,8 @@ static void ReorderBufferToastAppendChunk(ReorderBuffer *rb, ReorderBufferTXN *t
290290
*/
291291
static Size ReorderBufferChangeSize(ReorderBufferChange *change);
292292
static void ReorderBufferChangeMemoryUpdate(ReorderBuffer *rb,
293-
ReorderBufferChange *change, bool addition);
293+
ReorderBufferChange *change,
294+
bool addition, Size sz);
294295

295296
/*
296297
* Allocate a new ReorderBuffer and clean out any old serialized state from
@@ -474,7 +475,8 @@ ReorderBufferReturnChange(ReorderBuffer *rb, ReorderBufferChange *change,
474475
{
475476
/* update memory accounting info */
476477
if (upd_mem)
477-
ReorderBufferChangeMemoryUpdate(rb, change, false);
478+
ReorderBufferChangeMemoryUpdate(rb, change, false,
479+
ReorderBufferChangeSize(change));
478480

479481
/* free contained data */
480482
switch (change->action)
@@ -792,7 +794,8 @@ ReorderBufferQueueChange(ReorderBuffer *rb, TransactionId xid, XLogRecPtr lsn,
792794
txn->nentries_mem++;
793795

794796
/* update memory accounting information */
795-
ReorderBufferChangeMemoryUpdate(rb, change, true);
797+
ReorderBufferChangeMemoryUpdate(rb, change, true,
798+
ReorderBufferChangeSize(change));
796799

797800
/* process partial change */
798801
ReorderBufferProcessPartialChange(rb, txn, change, toast_insert);
@@ -3099,9 +3102,8 @@ ReorderBufferAddNewCommandId(ReorderBuffer *rb, TransactionId xid,
30993102
static void
31003103
ReorderBufferChangeMemoryUpdate(ReorderBuffer *rb,
31013104
ReorderBufferChange *change,
3102-
bool addition)
3105+
bool addition, Size sz)
31033106
{
3104-
Size sz;
31053107
ReorderBufferTXN *txn;
31063108
ReorderBufferTXN *toptxn;
31073109

@@ -3126,8 +3128,6 @@ ReorderBufferChangeMemoryUpdate(ReorderBuffer *rb,
31263128
else
31273129
toptxn = txn;
31283130

3129-
sz = ReorderBufferChangeSize(change);
3130-
31313131
if (addition)
31323132
{
31333133
txn->size += sz;
@@ -4358,7 +4358,8 @@ ReorderBufferRestoreChange(ReorderBuffer *rb, ReorderBufferTXN *txn,
43584358
* update the accounting too (subtracting the size from the counters). And
43594359
* we don't want to underflow there.
43604360
*/
4361-
ReorderBufferChangeMemoryUpdate(rb, change, true);
4361+
ReorderBufferChangeMemoryUpdate(rb, change, true,
4362+
ReorderBufferChangeSize(change));
43624363
}
43634364

43644365
/*
@@ -4604,17 +4605,23 @@ ReorderBufferToastReplace(ReorderBuffer *rb, ReorderBufferTXN *txn,
46044605
TupleDesc toast_desc;
46054606
MemoryContext oldcontext;
46064607
ReorderBufferTupleBuf *newtup;
4608+
Size old_size;
46074609

46084610
/* no toast tuples changed */
46094611
if (txn->toast_hash == NULL)
46104612
return;
46114613

46124614
/*
4613-
* We're going to modify the size of the change, so to make sure the
4614-
* accounting is correct we'll make it look like we're removing the change
4615-
* now (with the old size), and then re-add it at the end.
4615+
* We're going to modify the size of the change. So, to make sure the
4616+
* accounting is correct we record the current change size and then after
4617+
* re-computing the change we'll subtract the recorded size and then
4618+
* re-add the new change size at the end. We don't immediately subtract
4619+
* the old size because if there is any error before we add the new size,
4620+
* we will release the changes and that will update the accounting info
4621+
* (subtracting the size from the counters). And we don't want to
4622+
* underflow there.
46164623
*/
4617-
ReorderBufferChangeMemoryUpdate(rb, change, false);
4624+
old_size = ReorderBufferChangeSize(change);
46184625

46194626
oldcontext = MemoryContextSwitchTo(rb->context);
46204627

@@ -4765,8 +4772,11 @@ ReorderBufferToastReplace(ReorderBuffer *rb, ReorderBufferTXN *txn,
47654772

47664773
MemoryContextSwitchTo(oldcontext);
47674774

4775+
/* subtract the old change size */
4776+
ReorderBufferChangeMemoryUpdate(rb, change, false, old_size);
47684777
/* now add the change back, with the correct size */
4769-
ReorderBufferChangeMemoryUpdate(rb, change, true);
4778+
ReorderBufferChangeMemoryUpdate(rb, change, true,
4779+
ReorderBufferChangeSize(change));
47704780
}
47714781

47724782
/*

0 commit comments

Comments
 (0)