Skip to content

Commit 58cf794

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 b589d21 commit 58cf794

File tree

1 file changed

+23
-14
lines changed

1 file changed

+23
-14
lines changed

src/backend/replication/logical/reorderbuffer.c

Lines changed: 23 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -262,7 +262,8 @@ static void ReorderBufferToastAppendChunk(ReorderBuffer *rb, ReorderBufferTXN *t
262262
*/
263263
static Size ReorderBufferChangeSize(ReorderBufferChange *change);
264264
static void ReorderBufferChangeMemoryUpdate(ReorderBuffer *rb,
265-
ReorderBufferChange *change, bool addition);
265+
ReorderBufferChange *change,
266+
bool addition, Size sz);
266267

267268
/*
268269
* Allocate a new ReorderBuffer and clean out any old serialized state from
@@ -425,7 +426,8 @@ void
425426
ReorderBufferReturnChange(ReorderBuffer *rb, ReorderBufferChange *change)
426427
{
427428
/* update memory accounting info */
428-
ReorderBufferChangeMemoryUpdate(rb, change, false);
429+
ReorderBufferChangeMemoryUpdate(rb, change, false,
430+
ReorderBufferChangeSize(change));
429431

430432
/* free contained data */
431433
switch (change->action)
@@ -647,7 +649,8 @@ ReorderBufferQueueChange(ReorderBuffer *rb, TransactionId xid, XLogRecPtr lsn,
647649
txn->nentries_mem++;
648650

649651
/* update memory accounting information */
650-
ReorderBufferChangeMemoryUpdate(rb, change, true);
652+
ReorderBufferChangeMemoryUpdate(rb, change, true,
653+
ReorderBufferChangeSize(change));
651654

652655
/* check the memory limits and evict something if needed */
653656
ReorderBufferCheckMemoryLimit(rb);
@@ -2160,10 +2163,8 @@ ReorderBufferAddNewCommandId(ReorderBuffer *rb, TransactionId xid,
21602163
static void
21612164
ReorderBufferChangeMemoryUpdate(ReorderBuffer *rb,
21622165
ReorderBufferChange *change,
2163-
bool addition)
2166+
bool addition, Size sz)
21642167
{
2165-
Size sz;
2166-
21672168
Assert(change->txn);
21682169

21692170
/*
@@ -2174,8 +2175,6 @@ ReorderBufferChangeMemoryUpdate(ReorderBuffer *rb,
21742175
if (change->action == REORDER_BUFFER_CHANGE_INTERNAL_TUPLECID)
21752176
return;
21762177

2177-
sz = ReorderBufferChangeSize(change);
2178-
21792178
if (addition)
21802179
{
21812180
change->txn->size += sz;
@@ -3073,7 +3072,8 @@ ReorderBufferRestoreChange(ReorderBuffer *rb, ReorderBufferTXN *txn,
30733072
* update the accounting too (subtracting the size from the counters). And
30743073
* we don't want to underflow there.
30753074
*/
3076-
ReorderBufferChangeMemoryUpdate(rb, change, true);
3075+
ReorderBufferChangeMemoryUpdate(rb, change, true,
3076+
ReorderBufferChangeSize(change));
30773077
}
30783078

30793079
/*
@@ -3321,17 +3321,23 @@ ReorderBufferToastReplace(ReorderBuffer *rb, ReorderBufferTXN *txn,
33213321
TupleDesc toast_desc;
33223322
MemoryContext oldcontext;
33233323
ReorderBufferTupleBuf *newtup;
3324+
Size old_size;
33243325

33253326
/* no toast tuples changed */
33263327
if (txn->toast_hash == NULL)
33273328
return;
33283329

33293330
/*
3330-
* We're going to modify the size of the change, so to make sure the
3331-
* accounting is correct we'll make it look like we're removing the change
3332-
* now (with the old size), and then re-add it at the end.
3331+
* We're going to modify the size of the change. So, to make sure the
3332+
* accounting is correct we record the current change size and then after
3333+
* re-computing the change we'll subtract the recorded size and then
3334+
* re-add the new change size at the end. We don't immediately subtract
3335+
* the old size because if there is any error before we add the new size,
3336+
* we will release the changes and that will update the accounting info
3337+
* (subtracting the size from the counters). And we don't want to
3338+
* underflow there.
33333339
*/
3334-
ReorderBufferChangeMemoryUpdate(rb, change, false);
3340+
old_size = ReorderBufferChangeSize(change);
33353341

33363342
oldcontext = MemoryContextSwitchTo(rb->context);
33373343

@@ -3482,8 +3488,11 @@ ReorderBufferToastReplace(ReorderBuffer *rb, ReorderBufferTXN *txn,
34823488

34833489
MemoryContextSwitchTo(oldcontext);
34843490

3491+
/* subtract the old change size */
3492+
ReorderBufferChangeMemoryUpdate(rb, change, false, old_size);
34853493
/* now add the change back, with the correct size */
3486-
ReorderBufferChangeMemoryUpdate(rb, change, true);
3494+
ReorderBufferChangeMemoryUpdate(rb, change, true,
3495+
ReorderBufferChangeSize(change));
34873496
}
34883497

34893498
/*

0 commit comments

Comments
 (0)