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

Commitb381b58

Browse files
committed
Fix bugs in indexing of in-doubt HOT-updated tuples.
If we find a DELETE_IN_PROGRESS HOT-updated tuple, it is impossible to knowwhether to index it or not except by waiting to see if the deletingtransaction commits. If it doesn't, the tuple might again be LIVE, meaningwe have to index it. So wait and recheck in that case.Also, we must not rely on ii_BrokenHotChain to decide that it's possible toomit tuples from the index. That could result in omitting tuples that weneed, particularly in view of yesterday's fixes to not necessarily setindcheckxmin (but it's broken even without that, as per my analysis today).Since this is just an extremely marginal performance optimization, droppingthe test shouldn't hurt.These cases are only expected to happen in system catalogs (they'repossible there due to early release of RowExclusiveLock in mostcatalog-update code paths). Since reindexing of a system catalog isn't aparticularly performance-critical operation anyway, there's no real need tobe concerned about possible performance degradation from these changes.The worst aspects of this bug were introduced in 9.0 --- 8.x will alwayswait out a DELETE_IN_PROGRESS tuple. But I think dropping index entrieson the strength of ii_BrokenHotChain is dangerous even without that, soback-patch removal of that optimization to 8.3 and 8.4.
1 parent1d6249d commitb381b58

File tree

1 file changed

+42
-20
lines changed

1 file changed

+42
-20
lines changed

‎src/backend/catalog/index.c

Lines changed: 42 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1534,8 +1534,9 @@ index_build(Relation heapRelation,
15341534
*
15351535
* A side effect is to set indexInfo->ii_BrokenHotChain to true if we detect
15361536
* any potentially broken HOT chains. Currently, we set this if there are
1537-
* any RECENTLY_DEAD entries in a HOT chain, without trying very hard to
1538-
* detect whether they're really incompatible with the chain tip.
1537+
* any RECENTLY_DEAD or DELETE_IN_PROGRESS entries in a HOT chain, without
1538+
* trying very hard to detect whether they're really incompatible with the
1539+
* chain tip.
15391540
*/
15401541
double
15411542
IndexBuildHeapScan(RelationheapRelation,
@@ -1647,8 +1648,14 @@ IndexBuildHeapScan(Relation heapRelation,
16471648
* buffer continuously while visiting the page, so no pruning
16481649
* operation can occur either.
16491650
*
1651+
* Also, although our opinions about tuple liveness could change while
1652+
* we scan the page (due to concurrent transaction commits/aborts),
1653+
* the chain root locations won't, so this info doesn't need to be
1654+
* rebuilt after waiting for another transaction.
1655+
*
16501656
* Note the implied assumption that there is no more than one live
1651-
* tuple per HOT-chain ...
1657+
* tuple per HOT-chain --- else we could create more than one index
1658+
* entry pointing to the same root tuple.
16521659
*/
16531660
if (scan->rs_cblock!=root_blkno)
16541661
{
@@ -1702,20 +1709,13 @@ IndexBuildHeapScan(Relation heapRelation,
17021709
* the live tuple at the end of the HOT-chain.Since this
17031710
* breaks semantics for pre-existing snapshots, mark the
17041711
* index as unusable for them.
1705-
*
1706-
* If we've already decided that the index will be unsafe
1707-
* for old snapshots, we may as well stop indexing
1708-
* recently-dead tuples, since there's no longer any
1709-
* point.
17101712
*/
17111713
if (HeapTupleIsHotUpdated(heapTuple))
17121714
{
17131715
indexIt= false;
17141716
/* mark the index as unsafe for old snapshots */
17151717
indexInfo->ii_BrokenHotChain= true;
17161718
}
1717-
elseif (indexInfo->ii_BrokenHotChain)
1718-
indexIt= false;
17191719
else
17201720
indexIt= true;
17211721
/* In any case, exclude the tuple from unique-checking */
@@ -1765,7 +1765,8 @@ IndexBuildHeapScan(Relation heapRelation,
17651765
caseHEAPTUPLE_DELETE_IN_PROGRESS:
17661766

17671767
/*
1768-
* Similar situation to INSERT_IN_PROGRESS case.
1768+
* As with INSERT_IN_PROGRESS case, this is unexpected
1769+
* unless it's our own deletion or a system catalog.
17691770
*/
17701771
Assert(!(heapTuple->t_data->t_infomask&HEAP_XMAX_IS_MULTI));
17711772
xwait=HeapTupleHeaderGetXmax(heapTuple->t_data);
@@ -1780,8 +1781,17 @@ IndexBuildHeapScan(Relation heapRelation,
17801781
* the tuple is dead could lead to missing a
17811782
* uniqueness violation. In that case we wait for the
17821783
* deleting transaction to finish and check again.
1784+
*
1785+
* Also, if it's a HOT-updated tuple, we should not
1786+
* index it but rather the live tuple at the end of
1787+
* the HOT-chain. However, the deleting transaction
1788+
* could abort, possibly leaving this tuple as live
1789+
* after all, in which case it has to be indexed. The
1790+
* only way to know what to do is to wait for the
1791+
* deleting transaction to finish and check again.
17831792
*/
1784-
if (checking_uniqueness)
1793+
if (checking_uniqueness||
1794+
HeapTupleIsHotUpdated(heapTuple))
17851795
{
17861796
/*
17871797
* Must drop the lock on the buffer before we wait
@@ -1790,22 +1800,34 @@ IndexBuildHeapScan(Relation heapRelation,
17901800
XactLockTableWait(xwait);
17911801
gotorecheck;
17921802
}
1793-
}
17941803

1795-
/*
1796-
* Otherwise, we have to treat these tuples just like
1797-
* RECENTLY_DELETED ones.
1798-
*/
1799-
if (HeapTupleIsHotUpdated(heapTuple))
1804+
/*
1805+
* Otherwise index it but don't check for uniqueness,
1806+
* the same as a RECENTLY_DEAD tuple.
1807+
*/
1808+
indexIt= true;
1809+
}
1810+
elseif (HeapTupleIsHotUpdated(heapTuple))
18001811
{
1812+
/*
1813+
* It's a HOT-updated tuple deleted by our own xact.
1814+
* We can assume the deletion will commit (else the
1815+
* index contents don't matter), so treat the same
1816+
* as RECENTLY_DEAD HOT-updated tuples.
1817+
*/
18011818
indexIt= false;
18021819
/* mark the index as unsafe for old snapshots */
18031820
indexInfo->ii_BrokenHotChain= true;
18041821
}
1805-
elseif (indexInfo->ii_BrokenHotChain)
1806-
indexIt= false;
18071822
else
1823+
{
1824+
/*
1825+
* It's a regular tuple deleted by our own xact.
1826+
* Index it but don't check for uniqueness, the same
1827+
* as a RECENTLY_DEAD tuple.
1828+
*/
18081829
indexIt= true;
1830+
}
18091831
/* In any case, exclude the tuple from unique-checking */
18101832
tupleIsAlive= false;
18111833
break;

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp