diff options
author | Robert Haas <rhaas@postgresql.org> | 2011-03-18 22:09:57 -0400 |
---|---|---|
committer | Robert Haas <rhaas@postgresql.org> | 2011-03-18 22:09:57 -0400 |
commit | fbcf4b92aa64d4577bcf25925b055316b978744a (patch) | |
tree | 6576b9572a2ced538a6ecd8a12af73938a8bdb83 | |
parent | 727589995a3e027046f0da7af6ba665b0b47f89f (diff) | |
download | postgresql-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.c | 15 |
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 |