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

Commitc899c68

Browse files
committed
Fix creation of partition descriptor during concurrent detach+drop
If a partition undergoes DETACH CONCURRENTLY immediately followed byDROP, this could cause a problem for a concurrent transactionrecomputing the partition descriptor when running a prepared statement,because it tries to dereference a pointer to a tuple that's not found ina catalog scan.The existing retry logic added in commitdbca346 is sufficient tocope with the overall problem, provided we don't try to dereference anon-existant heap tuple.Arguably, the code in RelationBuildPartitionDesc() has been wrong allalong, since no check was added in commit898e5e3 against receivinga NULL tuple from the catalog scan; that bug has only becomeuser-visible with DETACH CONCURRENTLY which was added in branch 14.Therefore, even though there's no known mechanism to cause a crashbecause of this, backpatch the addition of such a check to all supportedbranches. In branches prior to 14, this would cause the code to failwith a "missing relpartbound for relation XYZ" error instead ofcrashing; that's okay, because there are no reports of such behavioranyway.Author: Kuntal Ghosh <kuntalghosh.2007@gmail.com>Reviewed-by: Junwang Zhao <zhjwpku@gmail.com>Reviewed-by: Tender Wang <tndrwang@gmail.com>Discussion:https://postgr.es/m/18559-b48286d2eacd9a4e@postgresql.org
1 parenta459ac5 commitc899c68

File tree

1 file changed

+22
-8
lines changed

1 file changed

+22
-8
lines changed

‎src/backend/partitioning/partdesc.c

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,10 @@ RelationBuildPartitionDesc(Relation rel, bool omit_detached)
209209
* shared queue. We solve this problem by reading pg_class directly
210210
* for the desired tuple.
211211
*
212+
* If the partition recently detached is also dropped, we get no tuple
213+
* from the scan. In that case, we also retry, and next time through
214+
* here, we don't see that partition anymore.
215+
*
212216
* The other problem is that DETACH CONCURRENTLY is in the process of
213217
* removing a partition, which happens in two steps: first it marks it
214218
* as "detach pending", commits, then unsets relpartbound. If
@@ -223,8 +227,6 @@ RelationBuildPartitionDesc(Relation rel, bool omit_detached)
223227
Relationpg_class;
224228
SysScanDescscan;
225229
ScanKeyDatakey[1];
226-
Datumdatum;
227-
boolisnull;
228230

229231
pg_class=table_open(RelationRelationId,AccessShareLock);
230232
ScanKeyInit(&key[0],
@@ -233,17 +235,29 @@ RelationBuildPartitionDesc(Relation rel, bool omit_detached)
233235
ObjectIdGetDatum(inhrelid));
234236
scan=systable_beginscan(pg_class,ClassOidIndexId, true,
235237
NULL,1,key);
238+
239+
/*
240+
* We could get one tuple from the scan (the normal case), or zero
241+
* tuples if the table has been dropped meanwhile.
242+
*/
236243
tuple=systable_getnext(scan);
237-
datum=heap_getattr(tuple,Anum_pg_class_relpartbound,
238-
RelationGetDescr(pg_class),&isnull);
239-
if (!isnull)
240-
boundspec=stringToNode(TextDatumGetCString(datum));
244+
if (HeapTupleIsValid(tuple))
245+
{
246+
Datumdatum;
247+
boolisnull;
248+
249+
datum=heap_getattr(tuple,Anum_pg_class_relpartbound,
250+
RelationGetDescr(pg_class),&isnull);
251+
if (!isnull)
252+
boundspec=stringToNode(TextDatumGetCString(datum));
253+
}
241254
systable_endscan(scan);
242255
table_close(pg_class,AccessShareLock);
243256

244257
/*
245-
* If we still don't get a relpartbound value, then it must be
246-
* because of DETACH CONCURRENTLY. Restart from the top, as
258+
* If we still don't get a relpartbound value (either because
259+
* boundspec is null or because there was no tuple), then it must
260+
* be because of DETACH CONCURRENTLY. Restart from the top, as
247261
* explained above. We only do this once, for two reasons: first,
248262
* only one DETACH CONCURRENTLY session could affect us at a time,
249263
* since each of them would have to wait for the snapshot under

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp