Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitc89d74c

Browse files
committed
Fix updates of indisvalid for partitioned indexes
indisvalid is switched to true for partitioned indexes when all itspartitions have valid indexes when attaching a new partition, up to thetop-most parent if all its leaves are themselves valid when dealing withmultiple layers of partitions.The copy of the tuple from pg_index used to switch indisvalid to truecame from the relation cache, which is incorrect. Particularly, in thecase reported by Shruthi Gowda, executing a series of commands in asingle transaction would cause the validation of partitioned indexes touse an incorrect version of a pg_index tuple, as indexes are reloadedafter an invalidation request with RelationReloadIndexInfo(), a muchfaster version than a full index cache rebuild. In this case, thelimited information updated in the cache leads to an incorrect versionof the tuple used. One of the symptoms reported was the followingerror, with a replica identity update, for instance:"ERROR: attempted to update invisible tuple"This is incorrect since8b08f7d, so backpatch all the way down.Reported-by: Shruthi GowdaAuthor: Michael PaquierReviewed-by: Shruthi Gowda, Dilip KumarDiscussion:https://postgr.es/m/CAASxf_PBcxax0wW-3gErUyftZ0XrCs3Lrpuhq4-Z3Fak1DoW7Q@mail.gmail.comBackpatch-through: 11
1 parent81ce000 commitc89d74c

File tree

3 files changed

+117
-4
lines changed

3 files changed

+117
-4
lines changed

‎src/backend/commands/tablecmds.c

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17884,17 +17884,24 @@ validatePartitionedIndex(Relation partedIdx, Relation partedTbl)
1788417884
if (tuples == RelationGetPartitionDesc(partedTbl)->nparts)
1788517885
{
1788617886
RelationidxRel;
17887-
HeapTuplenewtup;
17887+
HeapTupleindTup;
17888+
Form_pg_index indexForm;
1788817889

1788917890
idxRel = table_open(IndexRelationId, RowExclusiveLock);
17891+
indTup = SearchSysCacheCopy1(INDEXRELID,
17892+
ObjectIdGetDatum(RelationGetRelid(partedIdx)));
17893+
if (!HeapTupleIsValid(indTup))
17894+
elog(ERROR, "cache lookup failed for index %u",
17895+
RelationGetRelid(partedIdx));
17896+
indexForm = (Form_pg_index) GETSTRUCT(indTup);
1789017897

17891-
newtup = heap_copytuple(partedIdx->rd_indextuple);
17892-
((Form_pg_index) GETSTRUCT(newtup))->indisvalid = true;
17898+
indexForm->indisvalid = true;
1789317899
updated = true;
1789417900

17895-
CatalogTupleUpdate(idxRel, &partedIdx->rd_indextuple->t_self,newtup);
17901+
CatalogTupleUpdate(idxRel, &indTup->t_self,indTup);
1789617902

1789717903
table_close(idxRel, RowExclusiveLock);
17904+
heap_freetuple(indTup);
1789817905
}
1789917906

1790017907
/*

‎src/test/regress/expected/indexing.out

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1485,3 +1485,66 @@ select indexrelid::regclass, indisvalid,
14851485
(5 rows)
14861486

14871487
drop table parted_isvalid_tab;
1488+
-- Check state of replica indexes when attaching a partition.
1489+
begin;
1490+
create table parted_replica_tab (id int not null) partition by range (id);
1491+
create table parted_replica_tab_1 partition of parted_replica_tab
1492+
for values from (1) to (10) partition by range (id);
1493+
create table parted_replica_tab_11 partition of parted_replica_tab_1
1494+
for values from (1) to (5);
1495+
create unique index parted_replica_idx
1496+
on only parted_replica_tab using btree (id);
1497+
create unique index parted_replica_idx_1
1498+
on only parted_replica_tab_1 using btree (id);
1499+
-- This triggers an update of pg_index.indisreplident for parted_replica_idx.
1500+
alter table only parted_replica_tab_1 replica identity
1501+
using index parted_replica_idx_1;
1502+
create unique index parted_replica_idx_11 on parted_replica_tab_11 USING btree (id);
1503+
select indexrelid::regclass, indisvalid, indisreplident,
1504+
indrelid::regclass, inhparent::regclass
1505+
from pg_index idx left join
1506+
pg_inherits inh on (idx.indexrelid = inh.inhrelid)
1507+
where indexrelid::regclass::text like 'parted_replica%'
1508+
order by indexrelid::regclass::text collate "C";
1509+
indexrelid | indisvalid | indisreplident | indrelid | inhparent
1510+
-----------------------+------------+----------------+-----------------------+-----------
1511+
parted_replica_idx | f | f | parted_replica_tab |
1512+
parted_replica_idx_1 | f | t | parted_replica_tab_1 |
1513+
parted_replica_idx_11 | t | f | parted_replica_tab_11 |
1514+
(3 rows)
1515+
1516+
-- parted_replica_idx is not valid yet here, because parted_replica_idx_1
1517+
-- is not valid.
1518+
alter index parted_replica_idx ATTACH PARTITION parted_replica_idx_1;
1519+
select indexrelid::regclass, indisvalid, indisreplident,
1520+
indrelid::regclass, inhparent::regclass
1521+
from pg_index idx left join
1522+
pg_inherits inh on (idx.indexrelid = inh.inhrelid)
1523+
where indexrelid::regclass::text like 'parted_replica%'
1524+
order by indexrelid::regclass::text collate "C";
1525+
indexrelid | indisvalid | indisreplident | indrelid | inhparent
1526+
-----------------------+------------+----------------+-----------------------+--------------------
1527+
parted_replica_idx | f | f | parted_replica_tab |
1528+
parted_replica_idx_1 | f | t | parted_replica_tab_1 | parted_replica_idx
1529+
parted_replica_idx_11 | t | f | parted_replica_tab_11 |
1530+
(3 rows)
1531+
1532+
-- parted_replica_idx becomes valid here.
1533+
alter index parted_replica_idx_1 ATTACH PARTITION parted_replica_idx_11;
1534+
alter table only parted_replica_tab_1 replica identity
1535+
using index parted_replica_idx_1;
1536+
commit;
1537+
select indexrelid::regclass, indisvalid, indisreplident,
1538+
indrelid::regclass, inhparent::regclass
1539+
from pg_index idx left join
1540+
pg_inherits inh on (idx.indexrelid = inh.inhrelid)
1541+
where indexrelid::regclass::text like 'parted_replica%'
1542+
order by indexrelid::regclass::text collate "C";
1543+
indexrelid | indisvalid | indisreplident | indrelid | inhparent
1544+
-----------------------+------------+----------------+-----------------------+----------------------
1545+
parted_replica_idx | t | f | parted_replica_tab |
1546+
parted_replica_idx_1 | t | t | parted_replica_tab_1 | parted_replica_idx
1547+
parted_replica_idx_11 | t | f | parted_replica_tab_11 | parted_replica_idx_1
1548+
(3 rows)
1549+
1550+
drop table parted_replica_tab;

‎src/test/regress/sql/indexing.sql

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -808,3 +808,46 @@ select indexrelid::regclass, indisvalid,
808808
where indexrelid::regclass::textlike'parted_isvalid%'
809809
order by indexrelid::regclass::text collate"C";
810810
droptable parted_isvalid_tab;
811+
812+
-- Check state of replica indexes when attaching a partition.
813+
begin;
814+
createtableparted_replica_tab (idintnot null) partition by range (id);
815+
createtableparted_replica_tab_1 partition of parted_replica_tab
816+
forvaluesfrom (1) to (10) partition by range (id);
817+
createtableparted_replica_tab_11 partition of parted_replica_tab_1
818+
forvaluesfrom (1) to (5);
819+
createunique indexparted_replica_idx
820+
on only parted_replica_tab using btree (id);
821+
createunique indexparted_replica_idx_1
822+
on only parted_replica_tab_1 using btree (id);
823+
-- This triggers an update of pg_index.indisreplident for parted_replica_idx.
824+
altertable only parted_replica_tab_1 replica identity
825+
using index parted_replica_idx_1;
826+
createunique indexparted_replica_idx_11on parted_replica_tab_11 USING btree (id);
827+
select indexrelid::regclass, indisvalid, indisreplident,
828+
indrelid::regclass, inhparent::regclass
829+
from pg_index idxleft join
830+
pg_inherits inhon (idx.indexrelid=inh.inhrelid)
831+
where indexrelid::regclass::textlike'parted_replica%'
832+
order by indexrelid::regclass::text collate"C";
833+
-- parted_replica_idx is not valid yet here, because parted_replica_idx_1
834+
-- is not valid.
835+
alterindex parted_replica_idx ATTACH PARTITION parted_replica_idx_1;
836+
select indexrelid::regclass, indisvalid, indisreplident,
837+
indrelid::regclass, inhparent::regclass
838+
from pg_index idxleft join
839+
pg_inherits inhon (idx.indexrelid=inh.inhrelid)
840+
where indexrelid::regclass::textlike'parted_replica%'
841+
order by indexrelid::regclass::text collate"C";
842+
-- parted_replica_idx becomes valid here.
843+
alterindex parted_replica_idx_1 ATTACH PARTITION parted_replica_idx_11;
844+
altertable only parted_replica_tab_1 replica identity
845+
using index parted_replica_idx_1;
846+
commit;
847+
select indexrelid::regclass, indisvalid, indisreplident,
848+
indrelid::regclass, inhparent::regclass
849+
from pg_index idxleft join
850+
pg_inherits inhon (idx.indexrelid=inh.inhrelid)
851+
where indexrelid::regclass::textlike'parted_replica%'
852+
order by indexrelid::regclass::text collate"C";
853+
droptable parted_replica_tab;

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp