mirror of
https://github.com/postgres/postgres.git
synced 2025-06-27 23:21:58 +03:00
Fix re-distributing previously distributed invalidation messages during logical decoding.
Commit4909b38af0
introduced logic to distribute invalidation messages from catalog-modifying transactions to all concurrent in-progress transactions. However, since each transaction distributes not only its original invalidation messages but also previously distributed messages to other transactions, this leads to an exponential increase in allocation request size for invalidation messages, ultimately causing memory allocation failure. This commit fixes this issue by tracking distributed invalidation messages separately per decoded transaction and not redistributing these messages to other in-progress transactions. The maximum size of distributed invalidation messages that one transaction can store is limited to MAX_DISTR_INVAL_MSG_PER_TXN (8MB). Once the size of the distributed invalidation messages exceeds this threshold, we invalidate all caches in locations where distributed invalidation messages need to be executed. Back-patch to all supported versions where we introduced the fix by commit4909b38af0
. Note that this commit adds two new fields to ReorderBufferTXN to store the distributed transactions. This change breaks ABI compatibility in back branches, affecting third-party extensions that depend on the size of the ReorderBufferTXN struct, though this scenario seems unlikely. Additionally, it adds a new flag to the txn_flags field of ReorderBufferTXN to indicate distributed invalidation message overflow. This should not affect existing implementations, as it is unlikely that third-party extensions use unused bits in the txn_flags field. Bug: #18938 #18942 Author: vignesh C <vignesh21@gmail.com> Reported-by: Duncan Sands <duncan.sands@deepbluecap.com> Reported-by: John Hutchins <john.hutchins@wicourts.gov> Reported-by: Laurence Parry <greenreaper@hotmail.com> Reported-by: Max Madden <maxmmadden@gmail.com> Reported-by: Braulio Fdo Gonzalez <brauliofg@gmail.com> Reviewed-by: Masahiko Sawada <sawada.mshk@gmail.com> Reviewed-by: Amit Kapila <amit.kapila16@gmail.com> Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com> Discussion: https://postgr.es/m/680bdaf6-f7d1-4536-b580-05c2760c67c6@deepbluecap.com Discussion: https://postgr.es/m/18942-0ab1e5ae156613ad@postgresql.org Discussion: https://postgr.es/m/18938-57c9a1c463b68ce0@postgresql.org Discussion: https://postgr.es/m/CAD1FGCT2sYrP_70RTuo56QTizyc+J3wJdtn2gtO3VttQFpdMZg@mail.gmail.com Discussion: https://postgr.es/m/CANO2=B=2BT1hSYCE=nuuTnVTnjidMg0+-FfnRnqM6kd23qoygg@mail.gmail.com Backpatch-through: 13
This commit is contained in:
@ -1,4 +1,4 @@
|
||||
Parsed test spec with 2 sessions
|
||||
Parsed test spec with 3 sessions
|
||||
|
||||
starting permutation: s1_insert_tbl1 s1_begin s1_insert_tbl1 s2_alter_pub_add_tbl s1_commit s1_insert_tbl1 s2_get_binary_changes
|
||||
step s1_insert_tbl1: INSERT INTO tbl1 (val1, val2) VALUES (1, 1);
|
||||
@ -18,3 +18,24 @@ count
|
||||
stop
|
||||
(1 row)
|
||||
|
||||
|
||||
starting permutation: s1_begin s1_insert_tbl1 s3_begin s3_insert_tbl1 s2_alter_pub_add_tbl s1_insert_tbl1 s1_commit s3_commit s2_get_binary_changes
|
||||
step s1_begin: BEGIN;
|
||||
step s1_insert_tbl1: INSERT INTO tbl1 (val1, val2) VALUES (1, 1);
|
||||
step s3_begin: BEGIN;
|
||||
step s3_insert_tbl1: INSERT INTO tbl1 (val1, val2) VALUES (2, 2);
|
||||
step s2_alter_pub_add_tbl: ALTER PUBLICATION pub ADD TABLE tbl1;
|
||||
step s1_insert_tbl1: INSERT INTO tbl1 (val1, val2) VALUES (1, 1);
|
||||
step s1_commit: COMMIT;
|
||||
step s3_commit: COMMIT;
|
||||
step s2_get_binary_changes: SELECT count(data) FROM pg_logical_slot_get_binary_changes('isolation_slot', NULL, NULL, 'proto_version', '1', 'publication_names', 'pub') WHERE get_byte(data, 0) = 73;
|
||||
count
|
||||
-----
|
||||
0
|
||||
(1 row)
|
||||
|
||||
?column?
|
||||
--------
|
||||
stop
|
||||
(1 row)
|
||||
|
||||
|
@ -28,5 +28,16 @@ setup { SET synchronous_commit=on; }
|
||||
step "s2_alter_pub_add_tbl" { ALTER PUBLICATION pub ADD TABLE tbl1; }
|
||||
step "s2_get_binary_changes" { SELECT count(data) FROM pg_logical_slot_get_binary_changes('isolation_slot', NULL, NULL, 'proto_version', '1', 'publication_names', 'pub') WHERE get_byte(data, 0) = 73; }
|
||||
|
||||
session "s3"
|
||||
setup { SET synchronous_commit=on; }
|
||||
step "s3_begin" { BEGIN; }
|
||||
step "s3_insert_tbl1" { INSERT INTO tbl1 (val1, val2) VALUES (2, 2); }
|
||||
step "s3_commit" { COMMIT; }
|
||||
|
||||
# Expect to get one insert change. LOGICAL_REP_MSG_INSERT = 'I'
|
||||
permutation "s1_insert_tbl1" "s1_begin" "s1_insert_tbl1" "s2_alter_pub_add_tbl" "s1_commit" "s1_insert_tbl1" "s2_get_binary_changes"
|
||||
|
||||
# Expect to get no change because both s1's and s3's transactions
|
||||
# use the snapshot from before adding the table tbl1 to the
|
||||
# publication by "s2_alter_pub_add_tbl".
|
||||
permutation "s1_begin" "s1_insert_tbl1" "s3_begin" "s3_insert_tbl1" "s2_alter_pub_add_tbl" "s1_insert_tbl1" "s1_commit" "s3_commit" "s2_get_binary_changes"
|
||||
|
Reference in New Issue
Block a user