Fix fetching default toast value during decoding of in-progress transactions.
During logical decoding of in-progress transactions, we perform the toast table scan while fetching the default toast value for an attribute. We forgot to initialize the flag during this scan to indicate that the system table scan is in progress. We need this flag to ensure that during logical decoding we never directly access the tableam or heap APIs because we check for concurrent aborts only in systable_* APIs. Reported-by: Alexander Lakhin Author: Takeshi Ideriha, Hou Zhijie Reviewed-by: Amit Kapila, Hou Zhijie Backpatch-through: 14 Discussion: https://postgr.es/m/18641-6687273b7f15269d@postgresql.org
This commit is contained in:
parent
aef75219cc
commit
8175a7d11f
@ -106,6 +106,26 @@ SELECT data FROM pg_logical_slot_get_changes('regression_slot', NULL,NULL, 'incl
|
|||||||
committing streamed transaction
|
committing streamed transaction
|
||||||
(17 rows)
|
(17 rows)
|
||||||
|
|
||||||
|
-- Test that accessing a TOAST table in streaming mode is allowed.
|
||||||
|
-- Create a table with a column that uses a TOASTed default value.
|
||||||
|
-- (temporarily hide query, to avoid the long CREATE TABLE stmt)
|
||||||
|
\set ECHO none
|
||||||
|
BEGIN;
|
||||||
|
INSERT INTO test_tab SELECT repeat('a', 6000) || g.i FROM generate_series(1, 350) g(i);
|
||||||
|
-- Force WAL flush, so that the above changes will be streamed.
|
||||||
|
SELECT 'force flush' FROM pg_switch_wal();
|
||||||
|
?column?
|
||||||
|
-------------
|
||||||
|
force flush
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT count(*) FROM pg_logical_slot_get_changes('regression_slot', NULL, NULL, 'include-xids', '0', 'skip-empty-xacts', '1', 'stream-changes', '1');
|
||||||
|
count
|
||||||
|
-------
|
||||||
|
315
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
COMMIT;
|
||||||
DROP TABLE stream_test;
|
DROP TABLE stream_test;
|
||||||
SELECT pg_drop_replication_slot('regression_slot');
|
SELECT pg_drop_replication_slot('regression_slot');
|
||||||
pg_drop_replication_slot
|
pg_drop_replication_slot
|
||||||
|
@ -44,5 +44,23 @@ toasted-123456789012345678901234567890123456789012345678901234567890123456789012
|
|||||||
|
|
||||||
SELECT data FROM pg_logical_slot_get_changes('regression_slot', NULL,NULL, 'include-xids', '0', 'skip-empty-xacts', '1', 'stream-changes', '1');
|
SELECT data FROM pg_logical_slot_get_changes('regression_slot', NULL,NULL, 'include-xids', '0', 'skip-empty-xacts', '1', 'stream-changes', '1');
|
||||||
|
|
||||||
|
-- Test that accessing a TOAST table in streaming mode is allowed.
|
||||||
|
|
||||||
|
-- Create a table with a column that uses a TOASTed default value.
|
||||||
|
-- (temporarily hide query, to avoid the long CREATE TABLE stmt)
|
||||||
|
\set ECHO none
|
||||||
|
SELECT 'CREATE TABLE test_tab (a text DEFAULT ''' || string_agg('toast value', '') || ''');' FROM generate_series(1, 4000)
|
||||||
|
\gexec
|
||||||
|
\set ECHO all
|
||||||
|
|
||||||
|
BEGIN;
|
||||||
|
INSERT INTO test_tab SELECT repeat('a', 6000) || g.i FROM generate_series(1, 350) g(i);
|
||||||
|
|
||||||
|
-- Force WAL flush, so that the above changes will be streamed.
|
||||||
|
SELECT 'force flush' FROM pg_switch_wal();
|
||||||
|
|
||||||
|
SELECT count(*) FROM pg_logical_slot_get_changes('regression_slot', NULL, NULL, 'include-xids', '0', 'skip-empty-xacts', '1', 'stream-changes', '1');
|
||||||
|
COMMIT;
|
||||||
|
|
||||||
DROP TABLE stream_test;
|
DROP TABLE stream_test;
|
||||||
SELECT pg_drop_replication_slot('regression_slot');
|
SELECT pg_drop_replication_slot('regression_slot');
|
||||||
|
@ -703,6 +703,14 @@ systable_beginscan_ordered(Relation heapRelation,
|
|||||||
index_rescan(sysscan->iscan, key, nkeys, NULL, 0);
|
index_rescan(sysscan->iscan, key, nkeys, NULL, 0);
|
||||||
sysscan->scan = NULL;
|
sysscan->scan = 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;
|
return sysscan;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -747,6 +755,14 @@ systable_endscan_ordered(SysScanDesc sysscan)
|
|||||||
index_endscan(sysscan->iscan);
|
index_endscan(sysscan->iscan);
|
||||||
if (sysscan->snapshot)
|
if (sysscan->snapshot)
|
||||||
UnregisterSnapshot(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);
|
pfree(sysscan);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user