The following bug has been logged on the website:
Bug reference: 18241
Logged by: Fei Changhong
Email address: feichanghong@qq.com
PostgreSQL version: 16.1
Operating system: Operating system: centos 7,Kernel version: 5.10.13
Description:
In scenarios involving subtransactions, we've discovered that Standby might
mark index items as DEAD, which contravenes the design principle that
"killed tuples" should not emerge during recovery, as stated in the comments
of the RelationGetIndexScan function:
/*
* During recovery we ignore killed tuples and don't bother to kill them
* either. We do this because the xmin on the primary node could easily
be
* later than the xmin on the standby node, so that what the primary
* thinks is killed is supposed to be visible on standby. So for correct
* MVCC for queries during recovery we must ignore these hints and check
* all tuples. Do *not* set ignore_killed_tuples to true when running in
a
* transaction that was started during recovery. xactStartedInRecovery
* should not be altered by index AMs.
*/
The issue can be reproduced through the following steps:
(1) Initialize data on the Primary
```
create table t(a int, b int);
alter table t alter column b type bigint;
```
(2)Standby gdb breakpoint at _bt_killitems
```
begin;
savepoint savepoint_a;
explain analyze select * from t;
```
We can observe that the query enters the _bt_killitems function, and an
index item is marked as dead by the ItemIdMarkDead.
We have analyzed the cause of the problem: The value of
IndexScanDesc->xactStartedInRecovery is a key condition for determining
whether an index item can be marked as DEAD. And it depends on
CurrentTransactionState->startedInRecovery. However, PushTransaction does
not assign a value to startedInRecovery when modifying
CurrentTransactionState.
Additionally, I have another question I'd like to ask: What specific
problems might arise from a Standby marking index items as DEAD?