Skip to content

Commit df3640e

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 fa703b3 commit df3640e

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);
@@ -3100,9 +3103,8 @@ ReorderBufferAddNewCommandId(ReorderBuffer *rb, TransactionId xid,
31003103
static void
31013104
ReorderBufferChangeMemoryUpdate(ReorderBuffer *rb,
31023105
ReorderBufferChange *change,
3103-
bool addition)
3106+
bool addition, Size sz)
31043107
{
3105-
Size sz;
31063108
ReorderBufferTXN *txn;
31073109
ReorderBufferTXN *toptxn;
31083110

@@ -3127,8 +3129,6 @@ ReorderBufferChangeMemoryUpdate(ReorderBuffer *rb,
31273129
else
31283130
toptxn = txn;
31293131

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

43654366
/*
@@ -4605,17 +4606,23 @@ ReorderBufferToastReplace(ReorderBuffer *rb, ReorderBufferTXN *txn,
46054606
TupleDesc toast_desc;
46064607
MemoryContext oldcontext;
46074608
ReorderBufferTupleBuf *newtup;
4609+
Size old_size;
46084610

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

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

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

@@ -4766,8 +4773,11 @@ ReorderBufferToastReplace(ReorderBuffer *rb, ReorderBufferTXN *txn,
47664773

47674774
MemoryContextSwitchTo(oldcontext);
47684775

4776+
/* subtract the old change size */
4777+
ReorderBufferChangeMemoryUpdate(rb, change, false, old_size);
47694778
/* now add the change back, with the correct size */
4770-
ReorderBufferChangeMemoryUpdate(rb, change, true);
4779+
ReorderBufferChangeMemoryUpdate(rb, change, true,
4780+
ReorderBufferChangeSize(change));
47714781
}
47724782

47734783
/*

0 commit comments

Comments
 (0)