Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 50742ae

Browse files
committed
Add WAL logging for CREATE/DROP DATABASE and CREATE/DROP TABLESPACE.
Fix TablespaceCreateDbspace() to be able to create a dummy directory in place of a dropped tablespace's symlink. This eliminates the open problem of a PANIC during WAL replay when a replayed action attempts to touch a file in a since-deleted tablespace. It also makes for a significant improvement in the usability of PITR replay.
1 parent ee66401 commit 50742ae

File tree

9 files changed

+483
-106
lines changed

9 files changed

+483
-106
lines changed

doc/src/sgml/backup.sgml

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<!--
2-
$PostgreSQL: pgsql/doc/src/sgml/backup.sgml,v 2.46 2004/08/08 04:34:43 tgl Exp $
2+
$PostgreSQL: pgsql/doc/src/sgml/backup.sgml,v 2.47 2004/08/29 21:08:47 tgl Exp $
33
-->
44
<chapter id="backup">
55
<title>Backup and Restore</title>
@@ -902,17 +902,9 @@ restore_command = 'cp /mnt/server/archivedir/%f %p'
902902

903903
<para>
904904
At this writing, there are several limitations of the on-line backup
905-
technique. These will probably be fixed in future releases.
905+
technique. These will probably be fixed in future releases:
906906

907907
<itemizedlist>
908-
<listitem>
909-
<para>
910-
The effects of <command>CREATE DATABASE</>, <command>DROP DATABASE</>,
911-
<command>CREATE TABLESPACE</>, and <command>DROP TABLESPACE</> are
912-
not fully reflected in the WAL log. It is recommended that you take
913-
a new base backup after performing one of these operations.
914-
</para>
915-
</listitem>
916908
<listitem>
917909
<para>
918910
Operations on non-btree indexes (hash, R-tree, and GiST indexes) are
@@ -932,7 +924,7 @@ restore_command = 'cp /mnt/server/archivedir/%f %p'
932924
since we may need to fix partially-written disk pages. It is not
933925
necessary to store so many page copies for PITR operations, however.
934926
An area for future development is to compress archived WAL data by
935-
removing unnecesssary page copies.
927+
removing unnecessary page copies.
936928
</para>
937929
</sect2>
938930
</sect1>

src/backend/access/transam/rmgr.c

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,29 +3,31 @@
33
*
44
* Resource managers definition
55
*
6-
* $PostgreSQL: pgsql/src/backend/access/transam/rmgr.c,v 1.15 2004/08/23 23:22:44 tgl Exp $
6+
* $PostgreSQL: pgsql/src/backend/access/transam/rmgr.c,v 1.16 2004/08/29 21:08:47 tgl Exp $
77
*/
88
#include "postgres.h"
99

10+
#include "access/clog.h"
1011
#include "access/gist.h"
1112
#include "access/hash.h"
1213
#include "access/heapam.h"
1314
#include "access/nbtree.h"
1415
#include "access/rtree.h"
15-
#include "access/clog.h"
1616
#include "access/xact.h"
1717
#include "access/xlog_internal.h"
18-
#include "storage/smgr.h"
18+
#include "commands/dbcommands.h"
1919
#include "commands/sequence.h"
20+
#include "commands/tablespace.h"
21+
#include "storage/smgr.h"
2022

2123

2224
const RmgrData RmgrTable[RM_MAX_ID + 1] = {
2325
{"XLOG", xlog_redo, xlog_undo, xlog_desc, NULL, NULL},
2426
{"Transaction", xact_redo, xact_undo, xact_desc, NULL, NULL},
2527
{"Storage", smgr_redo, smgr_undo, smgr_desc, NULL, NULL},
2628
{"CLOG", clog_redo, clog_undo, clog_desc, NULL, NULL},
27-
{"Reserved 4", NULL, NULL, NULL, NULL, NULL},
28-
{"Reserved 5", NULL, NULL, NULL, NULL, NULL},
29+
{"Database", dbase_redo, dbase_undo, dbase_desc, NULL, NULL},
30+
{"Tablespace", tblspc_redo, tblspc_undo, tblspc_desc, NULL, NULL},
2931
{"Reserved 6", NULL, NULL, NULL, NULL, NULL},
3032
{"Reserved 7", NULL, NULL, NULL, NULL, NULL},
3133
{"Reserved 8", NULL, NULL, NULL, NULL, NULL},

src/backend/commands/dbcommands.c

Lines changed: 146 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
*
1010
*
1111
* IDENTIFICATION
12-
* $PostgreSQL: pgsql/src/backend/commands/dbcommands.c,v 1.141 2004/08/29 05:06:41 momjian Exp $
12+
* $PostgreSQL: pgsql/src/backend/commands/dbcommands.c,v 1.142 2004/08/29 21:08:47 tgl Exp $
1313
*
1414
*-------------------------------------------------------------------------
1515
*/
@@ -385,6 +385,30 @@ createdb(const CreatedbStmt *stmt)
385385
(errmsg("could not initialize database directory")));
386386
}
387387
#endif /* WIN32 */
388+
389+
/* Record the filesystem change in XLOG */
390+
{
391+
xl_dbase_create_rec xlrec;
392+
XLogRecData rdata[3];
393+
394+
xlrec.db_id = dboid;
395+
rdata[0].buffer = InvalidBuffer;
396+
rdata[0].data = (char *) &xlrec;
397+
rdata[0].len = offsetof(xl_dbase_create_rec, src_path);
398+
rdata[0].next = &(rdata[1]);
399+
400+
rdata[1].buffer = InvalidBuffer;
401+
rdata[1].data = (char *) srcpath;
402+
rdata[1].len = strlen(srcpath) + 1;
403+
rdata[1].next = &(rdata[2]);
404+
405+
rdata[2].buffer = InvalidBuffer;
406+
rdata[2].data = (char *) dstpath;
407+
rdata[2].len = strlen(dstpath) + 1;
408+
rdata[2].next = NULL;
409+
410+
(void) XLogInsert(RM_DBASE_ID, XLOG_DBASE_CREATE, rdata);
411+
}
388412
}
389413
heap_endscan(scan);
390414
heap_close(rel, AccessShareLock);
@@ -970,11 +994,27 @@ remove_dbtablespaces(Oid db_id)
970994
}
971995

972996
if (!rmtree(dstpath, true))
973-
{
974997
ereport(WARNING,
975998
(errmsg("could not remove database directory \"%s\"",
976-
dstpath),
977-
errhint("Look in the postmaster's stderr log for more information.")));
999+
dstpath)));
1000+
1001+
/* Record the filesystem change in XLOG */
1002+
{
1003+
xl_dbase_drop_rec xlrec;
1004+
XLogRecData rdata[2];
1005+
1006+
xlrec.db_id = db_id;
1007+
rdata[0].buffer = InvalidBuffer;
1008+
rdata[0].data = (char *) &xlrec;
1009+
rdata[0].len = offsetof(xl_dbase_drop_rec, dir_path);
1010+
rdata[0].next = &(rdata[1]);
1011+
1012+
rdata[1].buffer = InvalidBuffer;
1013+
rdata[1].data = (char *) dstpath;
1014+
rdata[1].len = strlen(dstpath) + 1;
1015+
rdata[1].next = NULL;
1016+
1017+
(void) XLogInsert(RM_DBASE_ID, XLOG_DBASE_DROP, rdata);
9781018
}
9791019

9801020
pfree(dstpath);
@@ -1063,3 +1103,105 @@ get_database_name(Oid dbid)
10631103

10641104
return result;
10651105
}
1106+
1107+
/*
1108+
* DATABASE resource manager's routines
1109+
*/
1110+
void
1111+
dbase_redo(XLogRecPtr lsn, XLogRecord *record)
1112+
{
1113+
uint8 info = record->xl_info & ~XLR_INFO_MASK;
1114+
1115+
if (info == XLOG_DBASE_CREATE)
1116+
{
1117+
xl_dbase_create_rec *xlrec = (xl_dbase_create_rec *) XLogRecGetData(record);
1118+
char *dst_path = xlrec->src_path + strlen(xlrec->src_path) + 1;
1119+
struct stat st;
1120+
#ifndef WIN32
1121+
char buf[2 * MAXPGPATH + 100];
1122+
#endif
1123+
1124+
/*
1125+
* Our theory for replaying a CREATE is to forcibly drop the target
1126+
* subdirectory if present, then re-copy the source data. This
1127+
* may be more work than needed, but it is simple to implement.
1128+
*/
1129+
if (stat(dst_path, &st) == 0 && S_ISDIR(st.st_mode))
1130+
{
1131+
if (!rmtree(dst_path, true))
1132+
ereport(WARNING,
1133+
(errmsg("could not remove database directory \"%s\"",
1134+
dst_path)));
1135+
}
1136+
1137+
#ifndef WIN32
1138+
/*
1139+
* Copy this subdirectory to the new location
1140+
*
1141+
* XXX use of cp really makes this code pretty grotty, particularly
1142+
* with respect to lack of ability to report errors well. Someday
1143+
* rewrite to do it for ourselves.
1144+
*/
1145+
1146+
/* We might need to use cp -R one day for portability */
1147+
snprintf(buf, sizeof(buf), "cp -r '%s' '%s'",
1148+
xlrec->src_path, dst_path);
1149+
if (system(buf) != 0)
1150+
ereport(ERROR,
1151+
(errmsg("could not initialize database directory"),
1152+
errdetail("Failing system command was: %s", buf),
1153+
errhint("Look in the postmaster's stderr log for more information.")));
1154+
#else /* WIN32 */
1155+
if (copydir(xlrec->src_path, dst_path) != 0)
1156+
{
1157+
/* copydir should already have given details of its troubles */
1158+
ereport(ERROR,
1159+
(errmsg("could not initialize database directory")));
1160+
}
1161+
#endif /* WIN32 */
1162+
}
1163+
else if (info == XLOG_DBASE_DROP)
1164+
{
1165+
xl_dbase_drop_rec *xlrec = (xl_dbase_drop_rec *) XLogRecGetData(record);
1166+
1167+
/* Drop pages for this database that are in the shared buffer cache */
1168+
DropBuffers(xlrec->db_id);
1169+
1170+
if (!rmtree(xlrec->dir_path, true))
1171+
ereport(WARNING,
1172+
(errmsg("could not remove database directory \"%s\"",
1173+
xlrec->dir_path)));
1174+
}
1175+
else
1176+
elog(PANIC, "dbase_redo: unknown op code %u", info);
1177+
}
1178+
1179+
void
1180+
dbase_undo(XLogRecPtr lsn, XLogRecord *record)
1181+
{
1182+
elog(PANIC, "dbase_undo: unimplemented");
1183+
}
1184+
1185+
void
1186+
dbase_desc(char *buf, uint8 xl_info, char *rec)
1187+
{
1188+
uint8 info = xl_info & ~XLR_INFO_MASK;
1189+
1190+
if (info == XLOG_DBASE_CREATE)
1191+
{
1192+
xl_dbase_create_rec *xlrec = (xl_dbase_create_rec *) rec;
1193+
char *dst_path = xlrec->src_path + strlen(xlrec->src_path) + 1;
1194+
1195+
sprintf(buf + strlen(buf), "create db: %u copy \"%s\" to \"%s\"",
1196+
xlrec->db_id, xlrec->src_path, dst_path);
1197+
}
1198+
else if (info == XLOG_DBASE_DROP)
1199+
{
1200+
xl_dbase_drop_rec *xlrec = (xl_dbase_drop_rec *) rec;
1201+
1202+
sprintf(buf + strlen(buf), "drop db: %u directory: \"%s\"",
1203+
xlrec->db_id, xlrec->dir_path);
1204+
}
1205+
else
1206+
strcat(buf, "UNKNOWN");
1207+
}

0 commit comments

Comments
 (0)