agora inbox for [email protected]help / color / mirror / Atom feed
[PATCH v7 6/7] Row pattern recognition patch (tests). 1915+ messages / 2 participants [nested] [flat]
* [PATCH v7 6/7] Row pattern recognition patch (tests). @ 2023-09-22 04:53 Tatsuo Ishii <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Tatsuo Ishii @ 2023-09-22 04:53 UTC (permalink / raw) --- src/test/regress/expected/rpr.out | 594 +++++++++++++++++++++++++++++ src/test/regress/parallel_schedule | 2 +- src/test/regress/sql/rpr.sql | 292 ++++++++++++++ 3 files changed, 887 insertions(+), 1 deletion(-) create mode 100644 src/test/regress/expected/rpr.out create mode 100644 src/test/regress/sql/rpr.sql diff --git a/src/test/regress/expected/rpr.out b/src/test/regress/expected/rpr.out new file mode 100644 index 0000000000..97bdc630d1 --- /dev/null +++ b/src/test/regress/expected/rpr.out @@ -0,0 +1,594 @@ +-- +-- Test for row pattern definition clause +-- +CREATE TEMP TABLE stock ( + company TEXT, + tdate DATE, + price INTEGER + ); +INSERT INTO stock VALUES ('company1', '2023-07-01', 100); +INSERT INTO stock VALUES ('company1', '2023-07-02', 200); +INSERT INTO stock VALUES ('company1', '2023-07-03', 150); +INSERT INTO stock VALUES ('company1', '2023-07-04', 140); +INSERT INTO stock VALUES ('company1', '2023-07-05', 150); +INSERT INTO stock VALUES ('company1', '2023-07-06', 90); +INSERT INTO stock VALUES ('company1', '2023-07-07', 110); +INSERT INTO stock VALUES ('company1', '2023-07-08', 130); +INSERT INTO stock VALUES ('company1', '2023-07-09', 120); +INSERT INTO stock VALUES ('company1', '2023-07-10', 130); +INSERT INTO stock VALUES ('company2', '2023-07-01', 50); +INSERT INTO stock VALUES ('company2', '2023-07-02', 2000); +INSERT INTO stock VALUES ('company2', '2023-07-03', 1500); +INSERT INTO stock VALUES ('company2', '2023-07-04', 1400); +INSERT INTO stock VALUES ('company2', '2023-07-05', 1500); +INSERT INTO stock VALUES ('company2', '2023-07-06', 60); +INSERT INTO stock VALUES ('company2', '2023-07-07', 1100); +INSERT INTO stock VALUES ('company2', '2023-07-08', 1300); +INSERT INTO stock VALUES ('company2', '2023-07-09', 1200); +INSERT INTO stock VALUES ('company2', '2023-07-10', 1300); +SELECT * FROM stock; + company | tdate | price +----------+------------+------- + company1 | 07-01-2023 | 100 + company1 | 07-02-2023 | 200 + company1 | 07-03-2023 | 150 + company1 | 07-04-2023 | 140 + company1 | 07-05-2023 | 150 + company1 | 07-06-2023 | 90 + company1 | 07-07-2023 | 110 + company1 | 07-08-2023 | 130 + company1 | 07-09-2023 | 120 + company1 | 07-10-2023 | 130 + company2 | 07-01-2023 | 50 + company2 | 07-02-2023 | 2000 + company2 | 07-03-2023 | 1500 + company2 | 07-04-2023 | 1400 + company2 | 07-05-2023 | 1500 + company2 | 07-06-2023 | 60 + company2 | 07-07-2023 | 1100 + company2 | 07-08-2023 | 1300 + company2 | 07-09-2023 | 1200 + company2 | 07-10-2023 | 1300 +(20 rows) + +-- basic test using PREV +SELECT company, tdate, price, first_value(price) OVER w, last_value(price) OVER w, + nth_value(tdate, 2) OVER w AS nth_second + FROM stock + WINDOW w AS ( + PARTITION BY company + ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING + INITIAL + PATTERN (START UP+ DOWN+) + DEFINE + START AS TRUE, + UP AS price > PREV(price), + DOWN AS price < PREV(price) +); + company | tdate | price | first_value | last_value | nth_second +----------+------------+-------+-------------+------------+------------ + company1 | 07-01-2023 | 100 | 100 | 140 | 07-02-2023 + company1 | 07-02-2023 | 200 | | | + company1 | 07-03-2023 | 150 | | | + company1 | 07-04-2023 | 140 | | | + company1 | 07-05-2023 | 150 | | | + company1 | 07-06-2023 | 90 | 90 | 120 | 07-07-2023 + company1 | 07-07-2023 | 110 | | | + company1 | 07-08-2023 | 130 | | | + company1 | 07-09-2023 | 120 | | | + company1 | 07-10-2023 | 130 | | | + company2 | 07-01-2023 | 50 | 50 | 1400 | 07-02-2023 + company2 | 07-02-2023 | 2000 | | | + company2 | 07-03-2023 | 1500 | | | + company2 | 07-04-2023 | 1400 | | | + company2 | 07-05-2023 | 1500 | | | + company2 | 07-06-2023 | 60 | 60 | 1200 | 07-07-2023 + company2 | 07-07-2023 | 1100 | | | + company2 | 07-08-2023 | 1300 | | | + company2 | 07-09-2023 | 1200 | | | + company2 | 07-10-2023 | 1300 | | | +(20 rows) + +-- last_value() should remain consistent +SELECT company, tdate, price, last_value(price) OVER w + FROM stock + WINDOW w AS ( + PARTITION BY company + ORDER BY tdate + ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING + INITIAL + PATTERN (START UP+ DOWN+) + DEFINE + START AS TRUE, + UP AS price > PREV(price), + DOWN AS price < PREV(price) +); + company | tdate | price | last_value +----------+------------+-------+------------ + company1 | 07-01-2023 | 100 | 140 + company1 | 07-02-2023 | 200 | + company1 | 07-03-2023 | 150 | + company1 | 07-04-2023 | 140 | + company1 | 07-05-2023 | 150 | + company1 | 07-06-2023 | 90 | 120 + company1 | 07-07-2023 | 110 | + company1 | 07-08-2023 | 130 | + company1 | 07-09-2023 | 120 | + company1 | 07-10-2023 | 130 | + company2 | 07-01-2023 | 50 | 1400 + company2 | 07-02-2023 | 2000 | + company2 | 07-03-2023 | 1500 | + company2 | 07-04-2023 | 1400 | + company2 | 07-05-2023 | 1500 | + company2 | 07-06-2023 | 60 | 1200 + company2 | 07-07-2023 | 1100 | + company2 | 07-08-2023 | 1300 | + company2 | 07-09-2023 | 1200 | + company2 | 07-10-2023 | 1300 | +(20 rows) + +-- omit "START" in DEFINE but it is ok because "START AS TRUE" is +-- implicitly defined. per spec. +SELECT company, tdate, price, first_value(price) OVER w, last_value(price) OVER w, + nth_value(tdate, 2) OVER w AS nth_second + FROM stock + WINDOW w AS ( + PARTITION BY company + ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING + INITIAL + PATTERN (START UP+ DOWN+) + DEFINE + UP AS price > PREV(price), + DOWN AS price < PREV(price) +); + company | tdate | price | first_value | last_value | nth_second +----------+------------+-------+-------------+------------+------------ + company1 | 07-01-2023 | 100 | 100 | 140 | 07-02-2023 + company1 | 07-02-2023 | 200 | | | + company1 | 07-03-2023 | 150 | | | + company1 | 07-04-2023 | 140 | | | + company1 | 07-05-2023 | 150 | | | + company1 | 07-06-2023 | 90 | 90 | 120 | 07-07-2023 + company1 | 07-07-2023 | 110 | | | + company1 | 07-08-2023 | 130 | | | + company1 | 07-09-2023 | 120 | | | + company1 | 07-10-2023 | 130 | | | + company2 | 07-01-2023 | 50 | 50 | 1400 | 07-02-2023 + company2 | 07-02-2023 | 2000 | | | + company2 | 07-03-2023 | 1500 | | | + company2 | 07-04-2023 | 1400 | | | + company2 | 07-05-2023 | 1500 | | | + company2 | 07-06-2023 | 60 | 60 | 1200 | 07-07-2023 + company2 | 07-07-2023 | 1100 | | | + company2 | 07-08-2023 | 1300 | | | + company2 | 07-09-2023 | 1200 | | | + company2 | 07-10-2023 | 1300 | | | +(20 rows) + +-- the first row start with less than or equal to 100 +SELECT company, tdate, price, first_value(price) OVER w, last_value(price) OVER w + FROM stock + WINDOW w AS ( + PARTITION BY company + ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING + INITIAL + PATTERN (LOWPRICE UP+ DOWN+) + DEFINE + LOWPRICE AS price <= 100, + UP AS price > PREV(price), + DOWN AS price < PREV(price) +); + company | tdate | price | first_value | last_value +----------+------------+-------+-------------+------------ + company1 | 07-01-2023 | 100 | 100 | 140 + company1 | 07-02-2023 | 200 | | + company1 | 07-03-2023 | 150 | | + company1 | 07-04-2023 | 140 | | + company1 | 07-05-2023 | 150 | | + company1 | 07-06-2023 | 90 | 90 | 120 + company1 | 07-07-2023 | 110 | | + company1 | 07-08-2023 | 130 | | + company1 | 07-09-2023 | 120 | | + company1 | 07-10-2023 | 130 | | + company2 | 07-01-2023 | 50 | 50 | 1400 + company2 | 07-02-2023 | 2000 | | + company2 | 07-03-2023 | 1500 | | + company2 | 07-04-2023 | 1400 | | + company2 | 07-05-2023 | 1500 | | + company2 | 07-06-2023 | 60 | 60 | 1200 + company2 | 07-07-2023 | 1100 | | + company2 | 07-08-2023 | 1300 | | + company2 | 07-09-2023 | 1200 | | + company2 | 07-10-2023 | 1300 | | +(20 rows) + +-- second row raises 120% +SELECT company, tdate, price, first_value(price) OVER w, last_value(price) OVER w + FROM stock + WINDOW w AS ( + PARTITION BY company + ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING + INITIAL + PATTERN (LOWPRICE UP+ DOWN+) + DEFINE + LOWPRICE AS price <= 100, + UP AS price > PREV(price) * 1.2, + DOWN AS price < PREV(price) +); + company | tdate | price | first_value | last_value +----------+------------+-------+-------------+------------ + company1 | 07-01-2023 | 100 | 100 | 140 + company1 | 07-02-2023 | 200 | | + company1 | 07-03-2023 | 150 | | + company1 | 07-04-2023 | 140 | | + company1 | 07-05-2023 | 150 | | + company1 | 07-06-2023 | 90 | | + company1 | 07-07-2023 | 110 | | + company1 | 07-08-2023 | 130 | | + company1 | 07-09-2023 | 120 | | + company1 | 07-10-2023 | 130 | | + company2 | 07-01-2023 | 50 | 50 | 1400 + company2 | 07-02-2023 | 2000 | | + company2 | 07-03-2023 | 1500 | | + company2 | 07-04-2023 | 1400 | | + company2 | 07-05-2023 | 1500 | | + company2 | 07-06-2023 | 60 | | + company2 | 07-07-2023 | 1100 | | + company2 | 07-08-2023 | 1300 | | + company2 | 07-09-2023 | 1200 | | + company2 | 07-10-2023 | 1300 | | +(20 rows) + +-- using NEXT +SELECT company, tdate, price, first_value(price) OVER w, last_value(price) OVER w + FROM stock + WINDOW w AS ( + PARTITION BY company + ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING + INITIAL + PATTERN (START UPDOWN) + DEFINE + START AS TRUE, + UPDOWN AS price > PREV(price) AND price > NEXT(price) +); + company | tdate | price | first_value | last_value +----------+------------+-------+-------------+------------ + company1 | 07-01-2023 | 100 | 100 | 200 + company1 | 07-02-2023 | 200 | | + company1 | 07-03-2023 | 150 | | + company1 | 07-04-2023 | 140 | 140 | 150 + company1 | 07-05-2023 | 150 | | + company1 | 07-06-2023 | 90 | | + company1 | 07-07-2023 | 110 | 110 | 130 + company1 | 07-08-2023 | 130 | | + company1 | 07-09-2023 | 120 | | + company1 | 07-10-2023 | 130 | | + company2 | 07-01-2023 | 50 | 50 | 2000 + company2 | 07-02-2023 | 2000 | | + company2 | 07-03-2023 | 1500 | | + company2 | 07-04-2023 | 1400 | 1400 | 1500 + company2 | 07-05-2023 | 1500 | | + company2 | 07-06-2023 | 60 | | + company2 | 07-07-2023 | 1100 | 1100 | 1300 + company2 | 07-08-2023 | 1300 | | + company2 | 07-09-2023 | 1200 | | + company2 | 07-10-2023 | 1300 | | +(20 rows) + +-- using AFTER MATCH SKIP TO NEXT ROW +SELECT company, tdate, price, first_value(price) OVER w, last_value(price) OVER w + FROM stock + WINDOW w AS ( + PARTITION BY company + ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING + AFTER MATCH SKIP TO NEXT ROW + INITIAL + PATTERN (START UPDOWN) + DEFINE + START AS TRUE, + UPDOWN AS price > PREV(price) AND price > NEXT(price) +); + company | tdate | price | first_value | last_value +----------+------------+-------+-------------+------------ + company1 | 07-01-2023 | 100 | 100 | 200 + company1 | 07-02-2023 | 200 | | + company1 | 07-03-2023 | 150 | | + company1 | 07-04-2023 | 140 | 140 | 150 + company1 | 07-05-2023 | 150 | | + company1 | 07-06-2023 | 90 | | + company1 | 07-07-2023 | 110 | 110 | 130 + company1 | 07-08-2023 | 130 | | + company1 | 07-09-2023 | 120 | | + company1 | 07-10-2023 | 130 | | + company2 | 07-01-2023 | 50 | 50 | 2000 + company2 | 07-02-2023 | 2000 | | + company2 | 07-03-2023 | 1500 | | + company2 | 07-04-2023 | 1400 | 1400 | 1500 + company2 | 07-05-2023 | 1500 | | + company2 | 07-06-2023 | 60 | | + company2 | 07-07-2023 | 1100 | 1100 | 1300 + company2 | 07-08-2023 | 1300 | | + company2 | 07-09-2023 | 1200 | | + company2 | 07-10-2023 | 1300 | | +(20 rows) + +-- match everything +SELECT company, tdate, price, first_value(price) OVER w, last_value(price) OVER w + FROM stock + WINDOW w AS ( + PARTITION BY company + ORDER BY tdate + ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING + AFTER MATCH SKIP PAST LAST ROW + INITIAL + PATTERN (A+) + DEFINE + A AS TRUE +); + company | tdate | price | first_value | last_value +----------+------------+-------+-------------+------------ + company1 | 07-01-2023 | 100 | 100 | 130 + company1 | 07-02-2023 | 200 | | + company1 | 07-03-2023 | 150 | | + company1 | 07-04-2023 | 140 | | + company1 | 07-05-2023 | 150 | | + company1 | 07-06-2023 | 90 | | + company1 | 07-07-2023 | 110 | | + company1 | 07-08-2023 | 130 | | + company1 | 07-09-2023 | 120 | | + company1 | 07-10-2023 | 130 | | + company2 | 07-01-2023 | 50 | 50 | 1300 + company2 | 07-02-2023 | 2000 | | + company2 | 07-03-2023 | 1500 | | + company2 | 07-04-2023 | 1400 | | + company2 | 07-05-2023 | 1500 | | + company2 | 07-06-2023 | 60 | | + company2 | 07-07-2023 | 1100 | | + company2 | 07-08-2023 | 1300 | | + company2 | 07-09-2023 | 1200 | | + company2 | 07-10-2023 | 1300 | | +(20 rows) + +-- backtracking with reclassification of rows +-- using AFTER MATCH SKIP PAST LAST ROW +SELECT company, tdate, price, first_value(tdate) OVER w, last_value(tdate) OVER w + FROM stock + WINDOW w AS ( + PARTITION BY company + ORDER BY tdate + ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING + AFTER MATCH SKIP PAST LAST ROW + INITIAL + PATTERN (A+ B+) + DEFINE + A AS price > 100, + B AS price > 100 +); + company | tdate | price | first_value | last_value +----------+------------+-------+-------------+------------ + company1 | 07-01-2023 | 100 | | + company1 | 07-02-2023 | 200 | 07-02-2023 | 07-05-2023 + company1 | 07-03-2023 | 150 | | + company1 | 07-04-2023 | 140 | | + company1 | 07-05-2023 | 150 | | + company1 | 07-06-2023 | 90 | | + company1 | 07-07-2023 | 110 | 07-07-2023 | 07-10-2023 + company1 | 07-08-2023 | 130 | | + company1 | 07-09-2023 | 120 | | + company1 | 07-10-2023 | 130 | | + company2 | 07-01-2023 | 50 | | + company2 | 07-02-2023 | 2000 | 07-02-2023 | 07-05-2023 + company2 | 07-03-2023 | 1500 | | + company2 | 07-04-2023 | 1400 | | + company2 | 07-05-2023 | 1500 | | + company2 | 07-06-2023 | 60 | | + company2 | 07-07-2023 | 1100 | 07-07-2023 | 07-10-2023 + company2 | 07-08-2023 | 1300 | | + company2 | 07-09-2023 | 1200 | | + company2 | 07-10-2023 | 1300 | | +(20 rows) + +-- backtracking with reclassification of rows +-- using AFTER MATCH SKIP TO NEXT ROW +SELECT company, tdate, price, first_value(tdate) OVER w, last_value(tdate) OVER w + FROM stock + WINDOW w AS ( + PARTITION BY company + ORDER BY tdate + ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING + AFTER MATCH SKIP TO NEXT ROW + INITIAL + PATTERN (A+ B+) + DEFINE + A AS price > 100, + B AS price > 100 +); + company | tdate | price | first_value | last_value +----------+------------+-------+-------------+------------ + company1 | 07-01-2023 | 100 | | + company1 | 07-02-2023 | 200 | 07-02-2023 | 07-05-2023 + company1 | 07-03-2023 | 150 | 07-03-2023 | 07-05-2023 + company1 | 07-04-2023 | 140 | 07-04-2023 | 07-05-2023 + company1 | 07-05-2023 | 150 | | + company1 | 07-06-2023 | 90 | | + company1 | 07-07-2023 | 110 | 07-07-2023 | 07-10-2023 + company1 | 07-08-2023 | 130 | 07-08-2023 | 07-10-2023 + company1 | 07-09-2023 | 120 | 07-09-2023 | 07-10-2023 + company1 | 07-10-2023 | 130 | | + company2 | 07-01-2023 | 50 | | + company2 | 07-02-2023 | 2000 | 07-02-2023 | 07-05-2023 + company2 | 07-03-2023 | 1500 | 07-03-2023 | 07-05-2023 + company2 | 07-04-2023 | 1400 | 07-04-2023 | 07-05-2023 + company2 | 07-05-2023 | 1500 | | + company2 | 07-06-2023 | 60 | | + company2 | 07-07-2023 | 1100 | 07-07-2023 | 07-10-2023 + company2 | 07-08-2023 | 1300 | 07-08-2023 | 07-10-2023 + company2 | 07-09-2023 | 1200 | 07-09-2023 | 07-10-2023 + company2 | 07-10-2023 | 1300 | | +(20 rows) + +-- +-- Aggregates +-- +-- using AFTER MATCH SKIP PAST LAST ROW +SELECT company, tdate, price, + first_value(price) OVER w, + last_value(price) OVER w, + max(price) OVER w, + min(price) OVER w, + sum(price) OVER w, + avg(price) OVER w, + count(price) OVER w +FROM stock +WINDOW w AS ( +PARTITION BY company +ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING +AFTER MATCH SKIP PAST LAST ROW +INITIAL +PATTERN (START UP+ DOWN+) +DEFINE +START AS TRUE, +UP AS price > PREV(price), +DOWN AS price < PREV(price) +); + company | tdate | price | first_value | last_value | max | min | sum | avg | count +----------+------------+-------+-------------+------------+------+-----+------+-----------------------+------- + company1 | 07-01-2023 | 100 | 100 | 140 | 200 | 100 | 590 | 147.5000000000000000 | 4 + company1 | 07-02-2023 | 200 | | | | | | | + company1 | 07-03-2023 | 150 | | | | | | | + company1 | 07-04-2023 | 140 | | | | | | | + company1 | 07-05-2023 | 150 | | | | | | | 0 + company1 | 07-06-2023 | 90 | 90 | 120 | 130 | 90 | 450 | 112.5000000000000000 | 4 + company1 | 07-07-2023 | 110 | | | | | | | + company1 | 07-08-2023 | 130 | | | | | | | + company1 | 07-09-2023 | 120 | | | | | | | + company1 | 07-10-2023 | 130 | | | | | | | 0 + company2 | 07-01-2023 | 50 | 50 | 1400 | 2000 | 50 | 4950 | 1237.5000000000000000 | 4 + company2 | 07-02-2023 | 2000 | | | | | | | + company2 | 07-03-2023 | 1500 | | | | | | | + company2 | 07-04-2023 | 1400 | | | | | | | + company2 | 07-05-2023 | 1500 | | | | | | | 0 + company2 | 07-06-2023 | 60 | 60 | 1200 | 1300 | 60 | 3660 | 915.0000000000000000 | 4 + company2 | 07-07-2023 | 1100 | | | | | | | + company2 | 07-08-2023 | 1300 | | | | | | | + company2 | 07-09-2023 | 1200 | | | | | | | + company2 | 07-10-2023 | 1300 | | | | | | | 0 +(20 rows) + +-- using AFTER MATCH SKIP TO NEXT ROW +SELECT company, tdate, price, + first_value(price) OVER w, + last_value(price) OVER w, + max(price) OVER w, + min(price) OVER w, + sum(price) OVER w, + avg(price) OVER w, + count(price) OVER w +FROM stock +WINDOW w AS ( +PARTITION BY company +ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING +AFTER MATCH SKIP TO NEXT ROW +INITIAL +PATTERN (START UP+ DOWN+) +DEFINE +START AS TRUE, +UP AS price > PREV(price), +DOWN AS price < PREV(price) +); + company | tdate | price | first_value | last_value | max | min | sum | avg | count +----------+------------+-------+-------------+------------+------+------+------+-----------------------+------- + company1 | 07-01-2023 | 100 | 100 | 140 | 200 | 100 | 590 | 147.5000000000000000 | 4 + company1 | 07-02-2023 | 200 | | | | | | | 0 + company1 | 07-03-2023 | 150 | | | | | | | 0 + company1 | 07-04-2023 | 140 | 140 | 90 | 150 | 90 | 380 | 126.6666666666666667 | 3 + company1 | 07-05-2023 | 150 | | | | | | | 0 + company1 | 07-06-2023 | 90 | 90 | 120 | 130 | 90 | 450 | 112.5000000000000000 | 4 + company1 | 07-07-2023 | 110 | 110 | 120 | 130 | 110 | 360 | 120.0000000000000000 | 3 + company1 | 07-08-2023 | 130 | | | | | | | 0 + company1 | 07-09-2023 | 120 | | | | | | | 0 + company1 | 07-10-2023 | 130 | | | | | | | 0 + company2 | 07-01-2023 | 50 | 50 | 1400 | 2000 | 50 | 4950 | 1237.5000000000000000 | 4 + company2 | 07-02-2023 | 2000 | | | | | | | 0 + company2 | 07-03-2023 | 1500 | | | | | | | 0 + company2 | 07-04-2023 | 1400 | 1400 | 60 | 1500 | 60 | 2960 | 986.6666666666666667 | 3 + company2 | 07-05-2023 | 1500 | | | | | | | 0 + company2 | 07-06-2023 | 60 | 60 | 1200 | 1300 | 60 | 3660 | 915.0000000000000000 | 4 + company2 | 07-07-2023 | 1100 | 1100 | 1200 | 1300 | 1100 | 3600 | 1200.0000000000000000 | 3 + company2 | 07-08-2023 | 1300 | | | | | | | 0 + company2 | 07-09-2023 | 1200 | | | | | | | 0 + company2 | 07-10-2023 | 1300 | | | | | | | 0 +(20 rows) + +-- +-- Error cases +-- +-- row pattern definition variable name must not appear more than once +SELECT company, tdate, price, first_value(price) OVER w, last_value(price) OVER w + FROM stock + WINDOW w AS ( + PARTITION BY company + ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING + ORDER BY tdate + INITIAL + PATTERN (START UP+ DOWN+) + DEFINE + START AS TRUE, + UP AS price > PREV(price), + DOWN AS price < PREV(price), + UP AS price > PREV(price) +); +ERROR: syntax error at or near "ORDER" +LINE 6: ORDER BY tdate + ^ +-- pattern variable name must appear in DEFINE +SELECT company, tdate, price, first_value(price) OVER w, last_value(price) OVER w + FROM stock + WINDOW w AS ( + PARTITION BY company + ORDER BY tdate + ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING + INITIAL + PATTERN (START UP+ DOWN+ END) + DEFINE + START AS TRUE, + UP AS price > PREV(price), + DOWN AS price < PREV(price) +); +ERROR: syntax error at or near "END" +LINE 8: PATTERN (START UP+ DOWN+ END) + ^ +-- FRAME must start at current row when row patttern recognition is used +SELECT company, tdate, price, first_value(price) OVER w, last_value(price) OVER w + FROM stock + WINDOW w AS ( + PARTITION BY company + ORDER BY tdate + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + INITIAL + PATTERN (START UP+ DOWN+) + DEFINE + START AS TRUE, + UP AS price > PREV(price), + DOWN AS price < PREV(price) +); +ERROR: FRAME must start at current row when row patttern recognition is used +-- SEEK is not supported +SELECT company, tdate, price, first_value(price) OVER w, last_value(price) OVER w + FROM stock + WINDOW w AS ( + PARTITION BY company + ORDER BY tdate + ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING + AFTER MATCH SKIP TO NEXT ROW + SEEK + PATTERN (START UP+ DOWN+) + DEFINE + START AS TRUE, + UP AS price > PREV(price), + DOWN AS price < PREV(price) +); +ERROR: SEEK is not supported +LINE 8: SEEK + ^ +HINT: Use INITIAL. diff --git a/src/test/regress/parallel_schedule b/src/test/regress/parallel_schedule index 4df9d8503b..896531002b 100644 --- a/src/test/regress/parallel_schedule +++ b/src/test/regress/parallel_schedule @@ -98,7 +98,7 @@ test: publication subscription # Another group of parallel tests # select_views depends on create_view # ---------- -test: select_views portals_p2 foreign_key cluster dependency guc bitmapops combocid tsearch tsdicts foreign_data window xmlmap functional_deps advisory_lock indirect_toast equivclass +test: select_views portals_p2 foreign_key cluster dependency guc bitmapops combocid tsearch tsdicts foreign_data window xmlmap functional_deps advisory_lock indirect_toast equivclass rpr # ---------- # Another group of parallel tests (JSON related) diff --git a/src/test/regress/sql/rpr.sql b/src/test/regress/sql/rpr.sql new file mode 100644 index 0000000000..bdefd20647 --- /dev/null +++ b/src/test/regress/sql/rpr.sql @@ -0,0 +1,292 @@ +-- +-- Test for row pattern definition clause +-- + +CREATE TEMP TABLE stock ( + company TEXT, + tdate DATE, + price INTEGER + ); +INSERT INTO stock VALUES ('company1', '2023-07-01', 100); +INSERT INTO stock VALUES ('company1', '2023-07-02', 200); +INSERT INTO stock VALUES ('company1', '2023-07-03', 150); +INSERT INTO stock VALUES ('company1', '2023-07-04', 140); +INSERT INTO stock VALUES ('company1', '2023-07-05', 150); +INSERT INTO stock VALUES ('company1', '2023-07-06', 90); +INSERT INTO stock VALUES ('company1', '2023-07-07', 110); +INSERT INTO stock VALUES ('company1', '2023-07-08', 130); +INSERT INTO stock VALUES ('company1', '2023-07-09', 120); +INSERT INTO stock VALUES ('company1', '2023-07-10', 130); +INSERT INTO stock VALUES ('company2', '2023-07-01', 50); +INSERT INTO stock VALUES ('company2', '2023-07-02', 2000); +INSERT INTO stock VALUES ('company2', '2023-07-03', 1500); +INSERT INTO stock VALUES ('company2', '2023-07-04', 1400); +INSERT INTO stock VALUES ('company2', '2023-07-05', 1500); +INSERT INTO stock VALUES ('company2', '2023-07-06', 60); +INSERT INTO stock VALUES ('company2', '2023-07-07', 1100); +INSERT INTO stock VALUES ('company2', '2023-07-08', 1300); +INSERT INTO stock VALUES ('company2', '2023-07-09', 1200); +INSERT INTO stock VALUES ('company2', '2023-07-10', 1300); + +SELECT * FROM stock; + +-- basic test using PREV +SELECT company, tdate, price, first_value(price) OVER w, last_value(price) OVER w, + nth_value(tdate, 2) OVER w AS nth_second + FROM stock + WINDOW w AS ( + PARTITION BY company + ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING + INITIAL + PATTERN (START UP+ DOWN+) + DEFINE + START AS TRUE, + UP AS price > PREV(price), + DOWN AS price < PREV(price) +); + +-- last_value() should remain consistent +SELECT company, tdate, price, last_value(price) OVER w + FROM stock + WINDOW w AS ( + PARTITION BY company + ORDER BY tdate + ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING + INITIAL + PATTERN (START UP+ DOWN+) + DEFINE + START AS TRUE, + UP AS price > PREV(price), + DOWN AS price < PREV(price) +); + +-- omit "START" in DEFINE but it is ok because "START AS TRUE" is +-- implicitly defined. per spec. +SELECT company, tdate, price, first_value(price) OVER w, last_value(price) OVER w, + nth_value(tdate, 2) OVER w AS nth_second + FROM stock + WINDOW w AS ( + PARTITION BY company + ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING + INITIAL + PATTERN (START UP+ DOWN+) + DEFINE + UP AS price > PREV(price), + DOWN AS price < PREV(price) +); + +-- the first row start with less than or equal to 100 +SELECT company, tdate, price, first_value(price) OVER w, last_value(price) OVER w + FROM stock + WINDOW w AS ( + PARTITION BY company + ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING + INITIAL + PATTERN (LOWPRICE UP+ DOWN+) + DEFINE + LOWPRICE AS price <= 100, + UP AS price > PREV(price), + DOWN AS price < PREV(price) +); + +-- second row raises 120% +SELECT company, tdate, price, first_value(price) OVER w, last_value(price) OVER w + FROM stock + WINDOW w AS ( + PARTITION BY company + ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING + INITIAL + PATTERN (LOWPRICE UP+ DOWN+) + DEFINE + LOWPRICE AS price <= 100, + UP AS price > PREV(price) * 1.2, + DOWN AS price < PREV(price) +); + +-- using NEXT +SELECT company, tdate, price, first_value(price) OVER w, last_value(price) OVER w + FROM stock + WINDOW w AS ( + PARTITION BY company + ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING + INITIAL + PATTERN (START UPDOWN) + DEFINE + START AS TRUE, + UPDOWN AS price > PREV(price) AND price > NEXT(price) +); + +-- using AFTER MATCH SKIP TO NEXT ROW +SELECT company, tdate, price, first_value(price) OVER w, last_value(price) OVER w + FROM stock + WINDOW w AS ( + PARTITION BY company + ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING + AFTER MATCH SKIP TO NEXT ROW + INITIAL + PATTERN (START UPDOWN) + DEFINE + START AS TRUE, + UPDOWN AS price > PREV(price) AND price > NEXT(price) +); + +-- match everything + +SELECT company, tdate, price, first_value(price) OVER w, last_value(price) OVER w + FROM stock + WINDOW w AS ( + PARTITION BY company + ORDER BY tdate + ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING + AFTER MATCH SKIP PAST LAST ROW + INITIAL + PATTERN (A+) + DEFINE + A AS TRUE +); + +-- backtracking with reclassification of rows +-- using AFTER MATCH SKIP PAST LAST ROW +SELECT company, tdate, price, first_value(tdate) OVER w, last_value(tdate) OVER w + FROM stock + WINDOW w AS ( + PARTITION BY company + ORDER BY tdate + ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING + AFTER MATCH SKIP PAST LAST ROW + INITIAL + PATTERN (A+ B+) + DEFINE + A AS price > 100, + B AS price > 100 +); + +-- backtracking with reclassification of rows +-- using AFTER MATCH SKIP TO NEXT ROW +SELECT company, tdate, price, first_value(tdate) OVER w, last_value(tdate) OVER w + FROM stock + WINDOW w AS ( + PARTITION BY company + ORDER BY tdate + ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING + AFTER MATCH SKIP TO NEXT ROW + INITIAL + PATTERN (A+ B+) + DEFINE + A AS price > 100, + B AS price > 100 +); + +-- +-- Aggregates +-- + +-- using AFTER MATCH SKIP PAST LAST ROW +SELECT company, tdate, price, + first_value(price) OVER w, + last_value(price) OVER w, + max(price) OVER w, + min(price) OVER w, + sum(price) OVER w, + avg(price) OVER w, + count(price) OVER w +FROM stock +WINDOW w AS ( +PARTITION BY company +ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING +AFTER MATCH SKIP PAST LAST ROW +INITIAL +PATTERN (START UP+ DOWN+) +DEFINE +START AS TRUE, +UP AS price > PREV(price), +DOWN AS price < PREV(price) +); + +-- using AFTER MATCH SKIP TO NEXT ROW +SELECT company, tdate, price, + first_value(price) OVER w, + last_value(price) OVER w, + max(price) OVER w, + min(price) OVER w, + sum(price) OVER w, + avg(price) OVER w, + count(price) OVER w +FROM stock +WINDOW w AS ( +PARTITION BY company +ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING +AFTER MATCH SKIP TO NEXT ROW +INITIAL +PATTERN (START UP+ DOWN+) +DEFINE +START AS TRUE, +UP AS price > PREV(price), +DOWN AS price < PREV(price) +); + +-- +-- Error cases +-- + +-- row pattern definition variable name must not appear more than once +SELECT company, tdate, price, first_value(price) OVER w, last_value(price) OVER w + FROM stock + WINDOW w AS ( + PARTITION BY company + ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING + ORDER BY tdate + INITIAL + PATTERN (START UP+ DOWN+) + DEFINE + START AS TRUE, + UP AS price > PREV(price), + DOWN AS price < PREV(price), + UP AS price > PREV(price) +); + +-- pattern variable name must appear in DEFINE +SELECT company, tdate, price, first_value(price) OVER w, last_value(price) OVER w + FROM stock + WINDOW w AS ( + PARTITION BY company + ORDER BY tdate + ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING + INITIAL + PATTERN (START UP+ DOWN+ END) + DEFINE + START AS TRUE, + UP AS price > PREV(price), + DOWN AS price < PREV(price) +); + +-- FRAME must start at current row when row patttern recognition is used +SELECT company, tdate, price, first_value(price) OVER w, last_value(price) OVER w + FROM stock + WINDOW w AS ( + PARTITION BY company + ORDER BY tdate + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + INITIAL + PATTERN (START UP+ DOWN+) + DEFINE + START AS TRUE, + UP AS price > PREV(price), + DOWN AS price < PREV(price) +); + +-- SEEK is not supported +SELECT company, tdate, price, first_value(price) OVER w, last_value(price) OVER w + FROM stock + WINDOW w AS ( + PARTITION BY company + ORDER BY tdate + ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING + AFTER MATCH SKIP TO NEXT ROW + SEEK + PATTERN (START UP+ DOWN+) + DEFINE + START AS TRUE, + UP AS price > PREV(price), + DOWN AS price < PREV(price) +); -- 2.25.1 ----Next_Part(Fri_Sep_22_14_16_40_2023_530)-- Content-Type: Text/X-Patch; charset=us-ascii Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="v7-0007-Allow-to-print-raw-parse-tree.patch" ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --tbdehtstrqwksfdh-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
* [PATCH] Distinguish properly when database-specific transaction list should be used. @ 2026-05-06 07:38 Antonin Houska <[email protected]> 0 siblings, 0 replies; 1915+ messages in thread From: Antonin Houska @ 2026-05-06 07:38 UTC (permalink / raw) Currently, decoding session that relies on database-specific xl_running_xacts WAL records can also use some information of cluster-wide records and vice versa. Although this approach might reduce the total number of xl_running_xacts records, it's simply not correct. SnapBuildProcessRunningXacts() now decides at the very beginning whether particular record can be used or not. --- src/backend/replication/logical/snapbuild.c | 55 +++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index c8309b96ed4..b9661b7d70a 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1157,6 +1157,39 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact ReorderBufferTXN *txn; TransactionId xmin; + /* + * Each decoding session should use either cluster-wide snapshots or + * database-specific ones, but not both. Since the latter can have more + * recent value of oldestRunningXid, builder->xmin could go backwards if + * it was followed by cluster-wide snapshot - see the ->xmin adjustment + * below. + */ + if (!db_specific && OidIsValid(running->dbid)) + return; + + if (db_specific) + { + /* + * Make sure that we have the snapshots needed for startup, as well as + * those for regular cleanup: each time the cluster-wide snapshot is + * created (typically on slot creation or by checkpointer), the + * database-specific snapshot is requested here if the current session + * needs it. + */ + if (!OidIsValid(running->dbid)) + { + LogStandbySnapshot(MyDatabaseId); + + return; + } + /* + * Snapshots issued for other databases do not contain the information + * about transactions in our database. + */ + else if (running->dbid != MyDatabaseId) + return; + } + /* * If we're not consistent yet, inspect the record to see whether it * allows to get closer to being consistent. If we are consistent, dump @@ -1171,17 +1204,7 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact */ if (db_specific) { - /* - * If we must only keep track of transactions running in the - * current database, we need transaction info from exactly that - * database. - */ - if (running->dbid != MyDatabaseId) - { - LogStandbySnapshot(MyDatabaseId); - - return; - } + Assert(running->dbid == MyDatabaseId); /* * We'd better be able to check during scan if the plugin does not @@ -1198,16 +1221,6 @@ SnapBuildProcessRunningXacts(SnapBuild *builder, XLogRecPtr lsn, xl_running_xact else SnapBuildSerialize(builder, lsn); - /* - * Database specific transaction info may exist to reach CONSISTENT state - * faster, however the code below makes no use of it. Moreover, such - * record might cause problems because the following normal (cluster-wide) - * record can have lower value of oldestRunningXid. In that case, let's - * wait with the cleanup for the next regular cluster-wide record. - */ - if (OidIsValid(running->dbid)) - return; - /* * Update range of interesting xids based on the running xacts * information. We don't increase ->xmax using it, because once we are in -- 2.47.3 --=-=-=-- ^ permalink raw reply [nested|flat] 1915+ messages in thread
end of thread, other threads:[~2026-05-06 07:38 UTC | newest] Thread overview: 1915+ messages (download: mbox mbox.gz follow: Atom feed) -- links below jump to the message on this page -- 2023-09-22 04:53 [PATCH v7 6/7] Row pattern recognition patch (tests). Tatsuo Ishii <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH 3/3] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]> 2026-05-06 07:38 [PATCH] Distinguish properly when database-specific transaction list should be used. Antonin Houska <[email protected]>
This inbox is served by agora; see mirroring instructions for how to clone and mirror all data and code used for this inbox