Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit07e3641

Browse files
committed
Avoid throwing ERROR during WAL replay of DROP TABLESPACE.
Although we will not even issue an XLOG_TBLSPC_DROP WAL record unlessremoval of the tablespace's directories succeeds, that does not guaranteethat the same operation will succeed during WAL replay. Foreseeablereasons for it to fail include temp files created in the tablespace by HotStandby backends, wrong directory permissions on a standby server, etc etc.The original coding threw ERROR if replay failed to remove the directories,but that is a serious overreaction. Throwing an error aborts recovery,and worse means that manual intervention will be needed to get the databaseto start again, since otherwise the same error will recur on subsequentattempts to replay the same WAL record. And the consequence of failing toremove the directories is only that some probably-small amount of diskspace is wasted, so it hardly seems justified to throw an error.Accordingly, arrange to report such failures as LOG messages and keep goingwhen a failure occurs during replay.Back-patch to 9.0 where Hot Standby was introduced. In principle suchproblems can occur in earlier releases, but Hot Standby increases the oddsof trouble significantly. Given the lack of field reports of such issues,I'm satisfied with patching back as far as the patch applies easily.
1 parent852a5cd commit07e3641

File tree

1 file changed

+47
-18
lines changed

1 file changed

+47
-18
lines changed

‎src/backend/commands/tablespace.c

Lines changed: 47 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -626,9 +626,13 @@ create_tablespace_directories(const char *location, const Oid tablespaceoid)
626626
/*
627627
* destroy_tablespace_directories
628628
*
629-
* Attempt to remove filesystem infrastructure
629+
* Attempt to remove filesystem infrastructure for the tablespace.
630630
*
631-
* 'redo' indicates we are redoing a drop from XLOG; okay if nothing there
631+
* 'redo' indicates we are redoing a drop from XLOG; in that case we should
632+
* not throw an ERROR for problems, just LOG them. The worst consequence of
633+
* not removing files here would be failure to release some disk space, which
634+
* does not justify throwing an error that would require manual intervention
635+
* to get the database running again.
632636
*
633637
* Returns TRUE if successful, FALSE if some subdirectory is not empty
634638
*/
@@ -681,6 +685,16 @@ destroy_tablespace_directories(Oid tablespaceoid, bool redo)
681685
pfree(linkloc_with_version_dir);
682686
return true;
683687
}
688+
elseif (redo)
689+
{
690+
/* in redo, just log other types of error */
691+
ereport(LOG,
692+
(errcode_for_file_access(),
693+
errmsg("could not open directory \"%s\": %m",
694+
linkloc_with_version_dir)));
695+
pfree(linkloc_with_version_dir);
696+
return false;
697+
}
684698
/* else let ReadDir report the error */
685699
}
686700

@@ -694,7 +708,7 @@ destroy_tablespace_directories(Oid tablespaceoid, bool redo)
694708
sprintf(subfile,"%s/%s",linkloc_with_version_dir,de->d_name);
695709

696710
/* This check is just to deliver a friendlier error message */
697-
if (!directory_is_empty(subfile))
711+
if (!redo&& !directory_is_empty(subfile))
698712
{
699713
FreeDir(dirdesc);
700714
pfree(subfile);
@@ -704,7 +718,7 @@ destroy_tablespace_directories(Oid tablespaceoid, bool redo)
704718

705719
/* remove empty directory */
706720
if (rmdir(subfile)<0)
707-
ereport(ERROR,
721+
ereport(redo ?LOG :ERROR,
708722
(errcode_for_file_access(),
709723
errmsg("could not remove directory \"%s\": %m",
710724
subfile)));
@@ -716,31 +730,38 @@ destroy_tablespace_directories(Oid tablespaceoid, bool redo)
716730

717731
/* remove version directory */
718732
if (rmdir(linkloc_with_version_dir)<0)
719-
ereport(ERROR,
733+
{
734+
ereport(redo ?LOG :ERROR,
720735
(errcode_for_file_access(),
721736
errmsg("could not remove directory \"%s\": %m",
722737
linkloc_with_version_dir)));
738+
pfree(linkloc_with_version_dir);
739+
return false;
740+
}
723741

724742
/*
725743
* Try to remove the symlink. We must however deal with the possibility
726744
* that it's a directory instead of a symlink --- this could happen during
727745
* WAL replay (see TablespaceCreateDbspace), and it is also the case on
728746
* Windows where junction points lstat() as directories.
747+
*
748+
* Note: in the redo case, we'll return true if this final step fails;
749+
* there's no point in retrying it.
729750
*/
730751
linkloc=pstrdup(linkloc_with_version_dir);
731752
get_parent_directory(linkloc);
732753
if (lstat(linkloc,&st)==0&&S_ISDIR(st.st_mode))
733754
{
734755
if (rmdir(linkloc)<0)
735-
ereport(ERROR,
756+
ereport(redo ?LOG :ERROR,
736757
(errcode_for_file_access(),
737758
errmsg("could not remove directory \"%s\": %m",
738759
linkloc)));
739760
}
740761
else
741762
{
742763
if (unlink(linkloc)<0)
743-
ereport(ERROR,
764+
ereport(redo ?LOG :ERROR,
744765
(errcode_for_file_access(),
745766
errmsg("could not remove symbolic link \"%s\": %m",
746767
linkloc)));
@@ -1413,30 +1434,38 @@ tblspc_redo(XLogRecPtr lsn, XLogRecord *record)
14131434
xl_tblspc_drop_rec*xlrec= (xl_tblspc_drop_rec*)XLogRecGetData(record);
14141435

14151436
/*
1416-
* If we issued a WAL record for a drop tablespace itis because there
1417-
* were no files in it at all. That means that no permanent objects
1418-
* can exist in it at this point.
1437+
* If we issued a WAL record for a drop tablespace itimplies that
1438+
*therewere no files in it at all when the DROP was done. That means
1439+
*that no permanent objectscan exist in it at this point.
14191440
*
14201441
* It is possible for standby users to be using this tablespace as a
14211442
* location for their temporary files, so if we fail to remove all
14221443
* files then do conflict processing and try again, if currently
14231444
* enabled.
1445+
*
1446+
* Other possible reasons for failure include bollixed file permissions
1447+
* on a standby server when they were okay on the primary, etc etc.
1448+
* There's not much we can do about that, so just remove what we can
1449+
* and press on.
14241450
*/
14251451
if (!destroy_tablespace_directories(xlrec->ts_id, true))
14261452
{
14271453
ResolveRecoveryConflictWithTablespace(xlrec->ts_id);
14281454

14291455
/*
14301456
* If we did recovery processing then hopefully the backends who
1431-
* wrote temp files should have cleaned up and exited by now. So
1432-
* lets recheck before we throw an error. If !process_conflicts
1433-
* then this will just fail again.
1457+
* wrote temp files should have cleaned up and exited by now. So
1458+
* retry before complaining. If we fail again, this is just a LOG
1459+
* condition, because it's not worth throwing an ERROR for (as
1460+
* that would crash the database and require manual intervention
1461+
* before we could get past this WAL record on restart).
14341462
*/
14351463
if (!destroy_tablespace_directories(xlrec->ts_id, true))
1436-
ereport(ERROR,
1464+
ereport(LOG,
14371465
(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
1438-
errmsg("tablespace %u is not empty",
1439-
xlrec->ts_id)));
1466+
errmsg("directories for tablespace %u could not be removed",
1467+
xlrec->ts_id),
1468+
errhint("You can remove the directories manually if necessary.")));
14401469
}
14411470
}
14421471
else
@@ -1452,14 +1481,14 @@ tblspc_desc(StringInfo buf, uint8 xl_info, char *rec)
14521481
{
14531482
xl_tblspc_create_rec*xlrec= (xl_tblspc_create_rec*)rec;
14541483

1455-
appendStringInfo(buf,"createts: %u \"%s\"",
1484+
appendStringInfo(buf,"createtablespace: %u \"%s\"",
14561485
xlrec->ts_id,xlrec->ts_path);
14571486
}
14581487
elseif (info==XLOG_TBLSPC_DROP)
14591488
{
14601489
xl_tblspc_drop_rec*xlrec= (xl_tblspc_drop_rec*)rec;
14611490

1462-
appendStringInfo(buf,"dropts: %u",xlrec->ts_id);
1491+
appendStringInfo(buf,"droptablespace: %u",xlrec->ts_id);
14631492
}
14641493
else
14651494
appendStringInfo(buf,"UNKNOWN");

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp