From: | Dmytro Astapov <dastapov(at)gmail(dot)com> |
---|---|
To: | pgsql-bugs(at)lists(dot)postgresql(dot)org |
Subject: | Parent index on partitioned table could still be invalid even when children are not |
Date: | 2025-01-23 19:09:45 |
Message-ID: | CAFQUnFj9SvgE_KB8NTmCBXDo2J7VsAVYoc0Uvtjx8fnLV6xRmg@mail.gmail.com |
Views: | Raw Message | Whole Thread | Download mbox | Resend email |
Thread: | |
Lists: | pgsql-bugs |
OS: Debian, Rock Linux
Postgres versions: 13.6, 15.6, 17.0
Setup:
create table tbl(id int, d date, payload text) partition by range(d);
create table tbl_2023 partition of tbl for values from ('2023-01-01') to
('2024-01-01');
create table tbl_2024 partition of tbl for values from ('2024-01-01') to
('2025-01-01');
-- Let's assume that the tbl is very large, as are the partitions,
-- so we are adding a new index by building it concurrently on partitions
and then creating
-- it on the parent table, which should attach partition indexes
create unique index concurrently on tbl_2023(d,id);
create unique index concurrently on tbl_2024(d,id);
-- Index on tbl_2024 ended up being invalid for whatever reason - in our
specific case it was deadlock
-- I am going to simulate this by marking index as invalid in pg_index
update pg_index set indisvalid='f' where indexrelid
='tbl_2024_d_id_idx'::regclass;
-- We failed to notice that partition index is invalid, and built parent
index anyway.
-- It was marked as invalid as well, so now we have two invalid indexes
create unique index on tbl(d,id);
select 'before', indexrelid::regclass from pg_index where not indisvalid ;
/* this outputs:
?column? indexrelid
before tbl_2024_d_id_idx
before tbl_d_id_idx
*/
-- We can fix the failed index on the partition with a simple reindex
reindex index concurrently tbl_2024_d_id_idx;
-- ... but this does not fix the index on parent, which is still invalid,
-- and there does not seem a way to make it valid
select 'after', indexrelid::regclass from pg_index where not indisvalid ;
/* this outputs:
?column? indexrelid
after tbl_d_id_idx
*/
At this point, there seems to be no way to make the parent index be valid.
It either can't be reindexed (in v13), or reindex does not mark it as valid
(v17). `reindex table tbl` does not mark it as valid either.
The only solution I was able to find is to detach all the partitions, drop
the index (reindex does not work at this stage either), create an index
again, and reattach all partitions:
alter table tbl detach partition tbl_2023;
alter table tbl detach partition tbl_2024;
drop index tbl_d_id_idx;
create unique index on tbl(d,id);
alter table tbl attach partition tbl_2023 for values from ('2023-01-01') to
('2024-01-01');
alter table tbl attach partition tbl_2024 for values from ('2024-01-01') to
('2025-01-01');
Alternatively, one can also DROP INDEX tbl_d_id_idx, which would drop all
index partitions, and start from scratch.
Here is db-fiddle for yor convenience if you want to play with it:
https://www.db-fiddle.com/f/b67c8CfQECbTpk3RXkXnPr/0
Unfortunately, in my practical case the tables involved are very large, so
detaching/reattaching partitions, or re-doing the index creation would lead
to couple of days of extra work and runtime.
I think the code involved here is contained in the
backend/commands/indexcmds.c
When the parent index is created, we arrive to this line
<https://github.com/postgres/postgres/blob/01463e1cccd33fb11b33a4dd6dbebcad3c534102/src/backend/commands/indexcmds.c#L1268>
in DefineIndex , where we would go over all indexes on partitions in search
for a matching one.
If a match is found, it would be attached to the parent, which happens here
<https://github.com/postgres/postgres/blob/01463e1cccd33fb11b33a4dd6dbebcad3c534102/src/backend/commands/indexcmds.c#L1421-L1441>.
However, if it is invalid, then invalidate_parent is set to true, and this
later triggers invalidation of the parent index a dozen of lines later, here
<https://github.com/postgres/postgres/blob/01463e1cccd33fb11b33a4dd6dbebcad3c534102/src/backend/commands/indexcmds.c#L1524-L1544>.
There does not seem to be a code path (outside of ALTER INDEX ... ATTACH
PARTITION ...) that could mark the parent index valid again.
This feels like a bug, with the expected behaviour being "once the last
invalid partition of an index becomes valid (and no partitions are
missing), the partitioned index should become valid as well". Would you
agree?
Also, is it naive to think that in this specific case marking the parent
index as valid via pg_index update might be warranted as a solution?
--
Best regards, Dmytro
From | Date | Subject | |
---|---|---|---|
Next Message | PG Bug reporting form | 2025-01-24 05:05:00 | BUG #18784: Bugs and BugTracking |
Previous Message | Tom Lane | 2025-01-23 18:09:48 | Re: BUG #18783: 2025-01-23 03:55:06.243 GMT [22929] LOG: postmaster became multithreaded 2025-01-23 03:55:06.243 GM |