aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobert Haas <rhaas@postgresql.org>2011-03-18 22:09:57 -0400
committerRobert Haas <rhaas@postgresql.org>2011-03-18 22:09:57 -0400
commitfbcf4b92aa64d4577bcf25925b055316b978744a (patch)
tree6576b9572a2ced538a6ecd8a12af73938a8bdb83
parent727589995a3e027046f0da7af6ba665b0b47f89f (diff)
downloadpostgresql-fbcf4b92aa64d4577bcf25925b055316b978744a.tar.gz
postgresql-fbcf4b92aa64d4577bcf25925b055316b978744a.zip
Fix possible "tuple concurrently updated" error in ALTER TABLE.
When adding an inheritance parent to a table, an AccessShareLock on the parent isn't strong enough to prevent trouble, so take ShareUpdateExclusiveLock instead. Since this is a behavior change, albeit a fairly unobtrusive one, and since we have only one report from the field, no back-patch. Report by Jon Nelson, analysis by Alvaro Herrera, fix by me.
-rw-r--r--src/backend/commands/tablecmds.c15
1 files changed, 11 insertions, 4 deletions
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index f1264bfb66d..ee34cfa97e1 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -1345,7 +1345,14 @@ MergeAttributes(List *schema, List *supers, char relpersistence,
AttrNumber *newattno;
AttrNumber parent_attno;
- relation = heap_openrv(parent, AccessShareLock);
+ /*
+ * A self-exclusive lock is needed here. If two backends attempt to
+ * add children to the same parent simultaneously, and that parent has
+ * no pre-existing children, then both will attempt to update the
+ * parent's relhassubclass field, leading to a "tuple concurrently
+ * updated" error.
+ */
+ relation = heap_openrv(parent, ShareUpdateExclusiveLock);
if (relation->rd_rel->relkind != RELKIND_RELATION)
ereport(ERROR,
@@ -7942,10 +7949,10 @@ ATExecAddInherit(Relation child_rel, RangeVar *parent, LOCKMODE lockmode)
List *children;
/*
- * AccessShareLock on the parent is what's obtained during normal CREATE
- * TABLE ... INHERITS ..., so should be enough here.
+ * A self-exclusive lock is needed here. See the similar case in
+ * MergeAttributes() for a full explanation.
*/
- parent_rel = heap_openrv(parent, AccessShareLock);
+ parent_rel = heap_openrv(parent, ShareUpdateExclusiveLock);
/*
* Must be owner of both parent and child -- child was checked by