diff options
author | Tom Lane | 2007-11-15 20:36:40 +0000 |
---|---|---|
committer | Tom Lane | 2007-11-15 20:36:40 +0000 |
commit | 6cc4451b5c47eac02e09c3342281da469374432d (patch) | |
tree | a97187cef1c3c2a95b7094fd46d68b0f448d7f33 /src/backend/commands/tablespace.c | |
parent | 7a550cb95cf3a541deed15df1d5e25f36af636e5 (diff) |
Prevent re-use of a deleted relation's relfilenode until after the next
checkpoint. This guards against an unlikely data-loss scenario in which
we re-use the relfilenode, then crash, then replay the deletion and
recreation of the file. Even then we'd be OK if all insertions into the
new relation had been WAL-logged ... but that's not guaranteed given all
the no-WAL-logging optimizations that have recently been added.
Patch by Heikki Linnakangas, per a discussion last month.
Diffstat (limited to 'src/backend/commands/tablespace.c')
-rw-r--r-- | src/backend/commands/tablespace.c | 29 |
1 files changed, 23 insertions, 6 deletions
diff --git a/src/backend/commands/tablespace.c b/src/backend/commands/tablespace.c index f19e237315e..305da59da00 100644 --- a/src/backend/commands/tablespace.c +++ b/src/backend/commands/tablespace.c @@ -37,7 +37,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/commands/tablespace.c,v 1.49 2007/08/01 22:45:08 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/commands/tablespace.c,v 1.50 2007/11/15 20:36:40 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -57,6 +57,7 @@ #include "commands/comment.h" #include "commands/tablespace.h" #include "miscadmin.h" +#include "postmaster/bgwriter.h" #include "storage/fd.h" #include "utils/acl.h" #include "utils/builtins.h" @@ -460,13 +461,29 @@ DropTableSpace(DropTableSpaceStmt *stmt) LWLockAcquire(TablespaceCreateLock, LW_EXCLUSIVE); /* - * Try to remove the physical infrastructure + * Try to remove the physical infrastructure. */ if (!remove_tablespace_directories(tablespaceoid, false)) - ereport(ERROR, - (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE), - errmsg("tablespace \"%s\" is not empty", - tablespacename))); + { + /* + * Not all files deleted? However, there can be lingering empty files + * in the directories, left behind by for example DROP TABLE, that + * have been scheduled for deletion at next checkpoint (see comments + * in mdunlink() for details). We could just delete them immediately, + * but we can't tell them apart from important data files that we + * mustn't delete. So instead, we force a checkpoint which will clean + * out any lingering files, and try again. + */ + RequestCheckpoint(CHECKPOINT_IMMEDIATE | CHECKPOINT_FORCE | CHECKPOINT_WAIT); + if (!remove_tablespace_directories(tablespaceoid, false)) + { + /* Still not empty, the files must be important then */ + ereport(ERROR, + (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE), + errmsg("tablespace \"%s\" is not empty", + tablespacename))); + } + } /* Record the filesystem change in XLOG */ { |