mirror of
https://github.com/postgres/postgres.git
synced 2025-09-02 04:21:28 +03:00
Implement streaming mode in ReorderBuffer.
Instead of serializing the transaction to disk after reaching the logical_decoding_work_mem limit in memory, we consume the changes we have in memory and invoke stream API methods added by commit45fdc9738b
. However, sometimes if we have incomplete toast or speculative insert we spill to the disk because we can't generate the complete tuple and stream. And, as soon as we get the complete tuple we stream the transaction including the serialized changes. We can do this incremental processing thanks to having assignments (associating subxact with toplevel xacts) in WAL right away, and thanks to logging the invalidation messages at each command end. These features are added by commits0bead9af48
andc55040ccd0
respectively. Now that we can stream in-progress transactions, the concurrent aborts may cause failures when the output plugin consults catalogs (both system and user-defined). We handle such failures by returning ERRCODE_TRANSACTION_ROLLBACK sqlerrcode from system table scan APIs to the backend or WALSender decoding a specific uncommitted transaction. The decoding logic on the receipt of such a sqlerrcode aborts the decoding of the current transaction and continue with the decoding of other transactions. We have ReorderBufferTXN pointer in each ReorderBufferChange by which we know which xact it belongs to. The output plugin can use this to decide which changes to discard in case of stream_abort_cb (e.g. when a subxact gets discarded). We also provide a new option via SQL APIs to fetch the changes being streamed. Author: Dilip Kumar, Tomas Vondra, Amit Kapila, Nikhil Sontakke Reviewed-by: Amit Kapila, Kuntal Ghosh, Ajin Cherian Tested-by: Neha Sharma, Mahendra Singh Thalor and Ajin Cherian Discussion: https://postgr.es/m/688b0b7f-2f6c-d827-c27b-216a8e3ea700@2ndquadrant.com
This commit is contained in:
@@ -28,6 +28,7 @@
|
||||
#include "lib/stringinfo.h"
|
||||
#include "miscadmin.h"
|
||||
#include "storage/bufmgr.h"
|
||||
#include "storage/procarray.h"
|
||||
#include "utils/acl.h"
|
||||
#include "utils/builtins.h"
|
||||
#include "utils/lsyscache.h"
|
||||
@@ -429,9 +430,36 @@ systable_beginscan(Relation heapRelation,
|
||||
sysscan->iscan = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* If CheckXidAlive is set then set a flag to indicate that system table
|
||||
* scan is in-progress. See detailed comments in xact.c where these
|
||||
* variables are declared.
|
||||
*/
|
||||
if (TransactionIdIsValid(CheckXidAlive))
|
||||
bsysscan = true;
|
||||
|
||||
return sysscan;
|
||||
}
|
||||
|
||||
/*
|
||||
* HandleConcurrentAbort - Handle concurrent abort of the CheckXidAlive.
|
||||
*
|
||||
* Error out, if CheckXidAlive is aborted. We can't directly use
|
||||
* TransactionIdDidAbort as after crash such transaction might not have been
|
||||
* marked as aborted. See detailed comments in xact.c where the variable
|
||||
* is declared.
|
||||
*/
|
||||
static inline void
|
||||
HandleConcurrentAbort()
|
||||
{
|
||||
if (TransactionIdIsValid(CheckXidAlive) &&
|
||||
!TransactionIdIsInProgress(CheckXidAlive) &&
|
||||
!TransactionIdDidCommit(CheckXidAlive))
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_TRANSACTION_ROLLBACK),
|
||||
errmsg("transaction aborted during system catalog scan")));
|
||||
}
|
||||
|
||||
/*
|
||||
* systable_getnext --- get next tuple in a heap-or-index scan
|
||||
*
|
||||
@@ -481,6 +509,12 @@ systable_getnext(SysScanDesc sysscan)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Handle the concurrent abort while fetching the catalog tuple during
|
||||
* logical streaming of a transaction.
|
||||
*/
|
||||
HandleConcurrentAbort();
|
||||
|
||||
return htup;
|
||||
}
|
||||
|
||||
@@ -517,6 +551,12 @@ systable_recheck_tuple(SysScanDesc sysscan, HeapTuple tup)
|
||||
sysscan->slot,
|
||||
freshsnap);
|
||||
|
||||
/*
|
||||
* Handle the concurrent abort while fetching the catalog tuple during
|
||||
* logical streaming of a transaction.
|
||||
*/
|
||||
HandleConcurrentAbort();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -545,6 +585,13 @@ systable_endscan(SysScanDesc sysscan)
|
||||
if (sysscan->snapshot)
|
||||
UnregisterSnapshot(sysscan->snapshot);
|
||||
|
||||
/*
|
||||
* Reset the bsysscan flag at the end of the systable scan. See
|
||||
* detailed comments in xact.c where these variables are declared.
|
||||
*/
|
||||
if (TransactionIdIsValid(CheckXidAlive))
|
||||
bsysscan = false;
|
||||
|
||||
pfree(sysscan);
|
||||
}
|
||||
|
||||
@@ -643,6 +690,12 @@ systable_getnext_ordered(SysScanDesc sysscan, ScanDirection direction)
|
||||
if (htup && sysscan->iscan->xs_recheck)
|
||||
elog(ERROR, "system catalog scans with lossy index conditions are not implemented");
|
||||
|
||||
/*
|
||||
* Handle the concurrent abort while fetching the catalog tuple during
|
||||
* logical streaming of a transaction.
|
||||
*/
|
||||
HandleConcurrentAbort();
|
||||
|
||||
return htup;
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user