Skip to content

Commit bf902c1

Browse files
committed
Revert "Fix replay of create database records on standby"
This reverts commit 49d9cfc. The approach taken by this patch has problems, so we'll come up with a radically different fix. Discussion: https://postgr.es/m/CA+TgmoYcUPL+WOJL2ZzhH=zmrhj0iOQ=iCFM0SuYqBbqZEamEg@mail.gmail.com
1 parent edea649 commit bf902c1

File tree

7 files changed

+1
-311
lines changed

7 files changed

+1
-311
lines changed

src/backend/access/transam/xlogrecovery.c

-6
Original file line numberDiff line numberDiff line change
@@ -2047,12 +2047,6 @@ CheckRecoveryConsistency(void)
20472047
*/
20482048
XLogCheckInvalidPages();
20492049

2050-
/*
2051-
* Check if the XLOG sequence contained any unresolved references to
2052-
* missing directories.
2053-
*/
2054-
XLogCheckMissingDirs();
2055-
20562050
reachedConsistency = true;
20572051
ereport(LOG,
20582052
(errmsg("consistent recovery state reached at %X/%X",

src/backend/access/transam/xlogutils.c

+1-158
Original file line numberDiff line numberDiff line change
@@ -54,164 +54,6 @@ bool InRecovery = false;
5454
/* Are we in Hot Standby mode? Only valid in startup process, see xlogutils.h */
5555
HotStandbyState standbyState = STANDBY_DISABLED;
5656

57-
58-
/*
59-
* If a create database WAL record is being replayed more than once during
60-
* crash recovery on a standby, it is possible that either the tablespace
61-
* directory or the template database directory is missing. This happens when
62-
* the directories are removed by replay of subsequent drop records. Note
63-
* that this problem happens only on standby and not on master. On master, a
64-
* checkpoint is created at the end of create database operation. On standby,
65-
* however, such a strategy (creating restart points during replay) is not
66-
* viable because it will slow down WAL replay.
67-
*
68-
* The alternative is to track references to each missing directory
69-
* encountered when performing crash recovery in the following hash table.
70-
* Similar to invalid page table above, the expectation is that each missing
71-
* directory entry should be matched with a drop database or drop tablespace
72-
* WAL record by the end of crash recovery.
73-
*/
74-
typedef struct xl_missing_dir_key
75-
{
76-
Oid spcNode;
77-
Oid dbNode;
78-
} xl_missing_dir_key;
79-
80-
typedef struct xl_missing_dir
81-
{
82-
xl_missing_dir_key key;
83-
char path[MAXPGPATH];
84-
} xl_missing_dir;
85-
86-
static HTAB *missing_dir_tab = NULL;
87-
88-
89-
/*
90-
* Keep track of a directory that wasn't found while replaying database
91-
* creation records. These should match up with tablespace removal records
92-
* later in the WAL stream; we verify that before reaching consistency.
93-
*/
94-
void
95-
XLogRememberMissingDir(Oid spcNode, Oid dbNode, char *path)
96-
{
97-
xl_missing_dir_key key;
98-
bool found;
99-
xl_missing_dir *entry;
100-
101-
/*
102-
* Database OID may be invalid but tablespace OID must be valid. If
103-
* dbNode is InvalidOid, we are logging a missing tablespace directory,
104-
* otherwise we are logging a missing database directory.
105-
*/
106-
Assert(OidIsValid(spcNode));
107-
108-
if (missing_dir_tab == NULL)
109-
{
110-
/* create hash table when first needed */
111-
HASHCTL ctl;
112-
113-
memset(&ctl, 0, sizeof(ctl));
114-
ctl.keysize = sizeof(xl_missing_dir_key);
115-
ctl.entrysize = sizeof(xl_missing_dir);
116-
117-
missing_dir_tab = hash_create("XLOG missing directory table",
118-
100,
119-
&ctl,
120-
HASH_ELEM | HASH_BLOBS);
121-
}
122-
123-
key.spcNode = spcNode;
124-
key.dbNode = dbNode;
125-
126-
entry = hash_search(missing_dir_tab, &key, HASH_ENTER, &found);
127-
128-
if (found)
129-
{
130-
if (dbNode == InvalidOid)
131-
elog(DEBUG1, "missing directory %s (tablespace %u) already exists: %s",
132-
path, spcNode, entry->path);
133-
else
134-
elog(DEBUG1, "missing directory %s (tablespace %u database %u) already exists: %s",
135-
path, spcNode, dbNode, entry->path);
136-
}
137-
else
138-
{
139-
strlcpy(entry->path, path, sizeof(entry->path));
140-
if (dbNode == InvalidOid)
141-
elog(DEBUG1, "logged missing dir %s (tablespace %u)",
142-
path, spcNode);
143-
else
144-
elog(DEBUG1, "logged missing dir %s (tablespace %u database %u)",
145-
path, spcNode, dbNode);
146-
}
147-
}
148-
149-
/*
150-
* Remove an entry from the list of directories not found. This is to be done
151-
* when the matching tablespace removal WAL record is found.
152-
*/
153-
void
154-
XLogForgetMissingDir(Oid spcNode, Oid dbNode)
155-
{
156-
xl_missing_dir_key key;
157-
158-
key.spcNode = spcNode;
159-
key.dbNode = dbNode;
160-
161-
/* Database OID may be invalid but tablespace OID must be valid. */
162-
Assert(OidIsValid(spcNode));
163-
164-
if (missing_dir_tab == NULL)
165-
return;
166-
167-
if (hash_search(missing_dir_tab, &key, HASH_REMOVE, NULL) != NULL)
168-
{
169-
if (dbNode == InvalidOid)
170-
{
171-
elog(DEBUG2, "forgot missing dir (tablespace %u)", spcNode);
172-
}
173-
else
174-
{
175-
char *path = GetDatabasePath(dbNode, spcNode);
176-
177-
elog(DEBUG2, "forgot missing dir %s (tablespace %u database %u)",
178-
path, spcNode, dbNode);
179-
pfree(path);
180-
}
181-
}
182-
}
183-
184-
/*
185-
* This is called at the end of crash recovery, before entering archive
186-
* recovery on a standby. PANIC if the hash table is not empty.
187-
*/
188-
void
189-
XLogCheckMissingDirs(void)
190-
{
191-
HASH_SEQ_STATUS status;
192-
xl_missing_dir *hentry;
193-
bool foundone = false;
194-
195-
if (missing_dir_tab == NULL)
196-
return; /* nothing to do */
197-
198-
hash_seq_init(&status, missing_dir_tab);
199-
200-
while ((hentry = (xl_missing_dir *) hash_seq_search(&status)) != NULL)
201-
{
202-
elog(WARNING, "missing directory \"%s\" tablespace %u database %u",
203-
hentry->path, hentry->key.spcNode, hentry->key.dbNode);
204-
foundone = true;
205-
}
206-
207-
if (foundone)
208-
elog(PANIC, "WAL contains references to missing directories");
209-
210-
hash_destroy(missing_dir_tab);
211-
missing_dir_tab = NULL;
212-
}
213-
214-
21557
/*
21658
* During XLOG replay, we may see XLOG records for incremental updates of
21759
* pages that no longer exist, because their relation was later dropped or
@@ -237,6 +79,7 @@ typedef struct xl_invalid_page
23779

23880
static HTAB *invalid_page_tab = NULL;
23981

82+
24083
/* Report a reference to an invalid page */
24184
static void
24285
report_invalid_page(int elevel, RelFileNode node, ForkNumber forkno,

src/backend/commands/dbcommands.c

-57
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,6 @@
3030
#include "access/tableam.h"
3131
#include "access/xact.h"
3232
#include "access/xloginsert.h"
33-
#include "access/xlogrecovery.h"
3433
#include "access/xlogutils.h"
3534
#include "catalog/catalog.h"
3635
#include "catalog/dependency.h"
@@ -2484,9 +2483,7 @@ dbase_redo(XLogReaderState *record)
24842483
xl_dbase_create_rec *xlrec = (xl_dbase_create_rec *) XLogRecGetData(record);
24852484
char *src_path;
24862485
char *dst_path;
2487-
char *parent_path;
24882486
struct stat st;
2489-
bool skip = false;
24902487

24912488
src_path = GetDatabasePath(xlrec->src_db_id, xlrec->src_tablespace_id);
24922489
dst_path = GetDatabasePath(xlrec->db_id, xlrec->tablespace_id);
@@ -2504,56 +2501,6 @@ dbase_redo(XLogReaderState *record)
25042501
(errmsg("some useless files may be left behind in old database directory \"%s\"",
25052502
dst_path)));
25062503
}
2507-
else if (!reachedConsistency)
2508-
{
2509-
/*
2510-
* It is possible that a drop tablespace record appearing later in
2511-
* WAL has already been replayed -- in other words, that we are
2512-
* replaying the database creation record a second time with no
2513-
* intervening checkpoint. In that case, the tablespace directory
2514-
* has already been removed and the create database operation
2515-
* cannot be replayed. Skip the replay itself, but remember the
2516-
* fact that the tablespace directory is missing, to be matched
2517-
* with the expected tablespace drop record later.
2518-
*/
2519-
parent_path = pstrdup(dst_path);
2520-
get_parent_directory(parent_path);
2521-
if (!(stat(parent_path, &st) == 0 && S_ISDIR(st.st_mode)))
2522-
{
2523-
XLogRememberMissingDir(xlrec->tablespace_id, InvalidOid, parent_path);
2524-
skip = true;
2525-
ereport(WARNING,
2526-
(errmsg("skipping replay of database creation WAL record"),
2527-
errdetail("The target tablespace \"%s\" directory was not found.",
2528-
parent_path),
2529-
errhint("A future WAL record that removes the directory before reaching consistent mode is expected.")));
2530-
}
2531-
pfree(parent_path);
2532-
}
2533-
2534-
/*
2535-
* If the source directory is missing, skip the copy and make a note of
2536-
* it for later.
2537-
*
2538-
* One possible reason for this is that the template database used for
2539-
* creating this database may have been dropped, as noted above.
2540-
* Moving a database from one tablespace may also be a partner in the
2541-
* crime.
2542-
*/
2543-
if (!(stat(src_path, &st) == 0 && S_ISDIR(st.st_mode)) &&
2544-
!reachedConsistency)
2545-
{
2546-
XLogRememberMissingDir(xlrec->src_tablespace_id, xlrec->src_db_id, src_path);
2547-
skip = true;
2548-
ereport(WARNING,
2549-
(errmsg("skipping replay of database creation WAL record"),
2550-
errdetail("The source database directory \"%s\" was not found.",
2551-
src_path),
2552-
errhint("A future WAL record that removes the directory before reaching consistent mode is expected.")));
2553-
}
2554-
2555-
if (skip)
2556-
return;
25572504

25582505
/*
25592506
* Force dirty buffers out to disk, to ensure source database is
@@ -2616,10 +2563,6 @@ dbase_redo(XLogReaderState *record)
26162563
ereport(WARNING,
26172564
(errmsg("some useless files may be left behind in old database directory \"%s\"",
26182565
dst_path)));
2619-
2620-
if (!reachedConsistency)
2621-
XLogForgetMissingDir(xlrec->tablespace_ids[i], xlrec->db_id);
2622-
26232566
pfree(dst_path);
26242567
}
26252568

src/backend/commands/tablespace.c

-17
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,6 @@
5757
#include "access/tableam.h"
5858
#include "access/xact.h"
5959
#include "access/xloginsert.h"
60-
#include "access/xlogrecovery.h"
6160
#include "access/xlogutils.h"
6261
#include "catalog/catalog.h"
6362
#include "catalog/dependency.h"
@@ -1575,22 +1574,6 @@ tblspc_redo(XLogReaderState *record)
15751574
{
15761575
xl_tblspc_drop_rec *xlrec = (xl_tblspc_drop_rec *) XLogRecGetData(record);
15771576

1578-
if (!reachedConsistency)
1579-
XLogForgetMissingDir(xlrec->ts_id, InvalidOid);
1580-
1581-
/*
1582-
* Before we remove the tablespace directory, update minimum recovery
1583-
* point to cover this WAL record. Once the tablespace is removed,
1584-
* there's no going back. This manually enforces the WAL-first rule.
1585-
* Doing this before the removal means that if the removal fails for
1586-
* some reason, the directory is left alone and needs to be manually
1587-
* removed. Alternatively we could update the minimum recovery point
1588-
* after removal, but that would leave a small window where the
1589-
* WAL-first rule could be violated.
1590-
*/
1591-
if (!reachedConsistency)
1592-
XLogFlush(record->EndRecPtr);
1593-
15941577
/*
15951578
* If we issued a WAL record for a drop tablespace it implies that
15961579
* there were no files in it at all when the DROP was done. That means

src/include/access/xlogutils.h

-4
Original file line numberDiff line numberDiff line change
@@ -65,10 +65,6 @@ extern void XLogDropDatabase(Oid dbid);
6565
extern void XLogTruncateRelation(RelFileNode rnode, ForkNumber forkNum,
6666
BlockNumber nblocks);
6767

68-
extern void XLogRememberMissingDir(Oid spcNode, Oid dbNode, char *path);
69-
extern void XLogForgetMissingDir(Oid spcNode, Oid dbNode);
70-
extern void XLogCheckMissingDirs(void);
71-
7268
/* Result codes for XLogReadBufferForRedo[Extended] */
7369
typedef enum
7470
{

src/test/recovery/t/029_replay_tsp_drops.pl

-67
This file was deleted.

src/tools/pgindent/typedefs.list

-2
Original file line numberDiff line numberDiff line change
@@ -3740,8 +3740,6 @@ xl_invalid_page
37403740
xl_invalid_page_key
37413741
xl_invalidations
37423742
xl_logical_message
3743-
xl_missing_dir_key
3744-
xl_missing_dir
37453743
xl_multi_insert_tuple
37463744
xl_multixact_create
37473745
xl_multixact_truncate

0 commit comments

Comments
 (0)