Re: [COMMITTERS] pgsql: Fix freezing of a dead HOT-updated tuple
Alvaro Herrera <alvherre@2ndquadrant.com>
From: Alvaro Herrera <alvherre@2ndquadrant.com>
To: Peter Geoghegan <pg@bowt.ie>
Cc: pgsql-hackers@postgresql.org, "Wood, Dan" <hexpert@amazon.com>
Date: 2017-10-03T16:48:20Z
Lists: pgsql-hackers
So here's my attempt at an explanation for what is going on. At one
point, we have this:
select lp, lp_flags, t_xmin, t_xmax, t_ctid, to_hex(t_infomask) as infomask,
to_hex(t_infomask2) as infomask2
from heap_page_items(get_raw_page('t', 0));
lp | lp_flags | t_xmin | t_xmax | t_ctid | infomask | infomask2
----+----------+--------+--------+--------+----------+-----------
1 | 1 | 2 | 0 | (0,1) | 902 | 3
2 | 0 | | | | |
3 | 1 | 2 | 19928 | (0,4) | 3142 | c003
4 | 1 | 14662 | 19929 | (0,5) | 3142 | c003
5 | 1 | 14663 | 19931 | (0,6) | 3142 | c003
6 | 1 | 14664 | 19933 | (0,7) | 3142 | c003
7 | 1 | 14665 | 0 | (0,7) | 2902 | 8003
(7 filas)
which shows a HOT-update chain, where the t_xmax are multixacts. Then a
vacuum freeze comes, and because the multixacts are below the freeze
horizon for multixacts, we get this:
select lp, lp_flags, t_xmin, t_xmax, t_ctid, to_hex(t_infomask) as infomask,
to_hex(t_infomask2) as infomask2
from heap_page_items(get_raw_page('t', 0));
lp | lp_flags | t_xmin | t_xmax | t_ctid | infomask | infomask2
----+----------+--------+--------+--------+----------+-----------
1 | 1 | 2 | 0 | (0,1) | 902 | 3
2 | 0 | | | | |
3 | 1 | 2 | 14662 | (0,4) | 2502 | c003
4 | 1 | 2 | 14663 | (0,5) | 2502 | c003
5 | 1 | 2 | 14664 | (0,6) | 2502 | c003
6 | 1 | 2 | 14665 | (0,7) | 2502 | c003
7 | 1 | 2 | 0 | (0,7) | 2902 | 8003
(7 filas)
where the xmin values have all been frozen, and the xmax values are now
regular Xids. I think the HOT code that walks the chain fails to detect
these as chains, because the xmin values no longer match the xmax
values. I modified the multixact freeze code, so that whenever the
update Xid is below the cutoff Xid, it's set to FrozenTransactionId,
since keeping the other value is invalid anyway (even though we have set
the HEAP_XMAX_COMMITTED flag). But that still doesn't fix the problem;
as far as I can see, vacuum removes the root of the chain, not yet sure
why, and then things are just as corrupted as before.
--
Álvaro Herrera https://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Remote DBA, Training & Services
Commits
-
Backport addition of rs_old_rel to rewriteheap's state.
- 152a56905658 9.3.21 landed
-
Perform a lot more sanity checks when freezing tuples.
- ed8e1aff6ace 9.4.16 landed
- d3044f8b0732 10.2 landed
- 986a9153b970 9.6.7 landed
- 94d1c88103ff 9.5.11 landed
- 4800f16a7ad0 9.3.21 landed
- 699bf7d05c68 11.0 landed
-
Revert bogus fixes of HOT-freezing bug
- c6764eb3aea6 11.0 landed
- f05ae2fa94b4 9.3.20 landed
- ef0339ee5dcf 9.4.15 landed
- b3888b60d3f0 9.5.10 landed
- 7a95966bc03c 10.1 landed
- 08ba67d596a1 9.6.6 landed
-
Fix traversal of half-frozen update chains
- a5736bf754c8 11.0 landed
- fc0df3bdafd6 9.5.10 landed
- d441cff14249 9.6.6 landed
- b052d524ca71 9.3.20 landed
- 8b6d85f2dc1e 9.4.15 landed
- 22576734b805 10.1 landed
-
Fix freezing of a dead HOT-updated tuple
- 46c35116ae1a 10.0 cited
- 20b655224249 11.0 cited
-
During index build, check and elog (not just Assert) for broken HOT chain.
- d70cf811f7dd 9.4.0 cited
-
Fix WAL replay of locking an updated tuple
- 6bfa88acd3df 9.4.0 cited
-
Change the way we mark tuples as frozen.
- 37484ad2aace 9.4.0 cited