1
0
mirror of https://github.com/pgbackrest/pgbackrest.git synced 2025-03-03 14:52:21 +02:00

Fixed an issue that prevented tablespaces from being backed up on PostgreSQL ≤ 8.4.

The integration tests that were supposed to prevent this regression did not work as intended.  They verified the contents of a table in the (supposedly) restored tablespace, deleted the table, and then deleted the tablespace.  All of this was deemed sufficient to prove that the tablespace had been restored correctly and was valid.

However, PostgreSQL will happily recreate a tablespace on the basis of a single full-page write, at least in the affected versions.  Since writes to the test table were replayed from WAL with each recovery, all the tests passed even though the tablespace was missing after the restore.

The tests have been updated to include direct comparisons against the file system and a new table that is not replayed after a restore because it is created before the backup and never modified again.

Versions ≥ 9.0 were not affected due to numerous synthetic integration tests that verify backups and restores file by file.
This commit is contained in:
David Steele 2017-06-27 16:47:40 -04:00
parent fdabf33604
commit 2310e423e9
3 changed files with 57 additions and 2 deletions

View File

@ -165,6 +165,8 @@
<release-list>
<release date="XXXX-XX-XX" version="1.20dev" title="UNDER DEVELOPMENT">
<release-core-list>
<p><b>IMPORTANT NOTE</b>: <postgres/> <proper>8.3</proper> and <proper>8.4</proper> installations utilizing tablespaces should upgrade immediately from any <id>1.XX</id> release and run a full backup. A bug prevented tablespaces from being backed up on these versions only. <postgres/> &amp;ge; <proper>9.0</proper> is not affected.</p>
<release-bug-list>
<release-item>
<release-item-contributor-list>
@ -173,6 +175,10 @@
<p>Fixed missing flag in C library build that resulted in a mismatched binary on 32-bit systems.</p>
</release-item>
<release-item>
<p>Fixed an issue that prevented tablespaces from being backed up on <postgres/> &amp;le; <proper>8.4</proper>.</p>
</release-item>
</release-bug-list>
<release-feature-list>

View File

@ -800,7 +800,12 @@ sub build
if ($bTablespace)
{
$strFilter = $self->tablespacePathGet();
# Only versions >= 9.0 have the special top-level tablespace path. Below 9.0 the database files are stored
# directly in the path referenced by the symlink.
if ($strDbVersion >= PG_VERSION_90)
{
$strFilter = $self->tablespacePathGet();
}
$self->set(MANIFEST_SECTION_TARGET_PATH, MANIFEST_TARGET_PGTBLSPC, undef,
$self->get(MANIFEST_SECTION_TARGET_PATH, MANIFEST_TARGET_PGDATA));

View File

@ -529,7 +529,10 @@ sub run
$oHostDbMaster->sqlExecute(
"create tablespace ts1 location '" . $oHostDbMaster->tablespacePath(1) . "'", {bAutoCommit => true});
$oHostDbMaster->sqlExecute("alter table test set tablespace ts1", {bCheckPoint => true});
$oHostDbMaster->sqlExecute("alter table test set tablespace ts1");
# Create a table in the tablespace that will not be modified again to be sure it does get full page writes in the WAL later
$oHostDbMaster->sqlExecute("create table test_exists (id int) tablespace ts1", {bCommit => true, bCheckPoint => true});
# Create a table in the tablespace
$oHostDbMaster->sqlExecute("create table test_remove (id int)");
@ -681,6 +684,47 @@ sub run
$oHostDbMaster->clusterStart();
$oHostDbMaster->sqlSelectOneTest('select message from test', $bTestLocal ? $strNameMessage : $strIncrMessage);
# The tablespace path should exist and have files in it
my $strTablespacePath = $oHostDbMaster->tablespacePath(1);
# Version <= 8.4 always places a PG_VERSION file in the tablespace
if ($oHostDbMaster->pgVersion() <= PG_VERSION_84)
{
if (!storageDb()->exists("${strTablespacePath}/" . DB_FILE_PGVERSION))
{
confess &log(ASSERT, "unable to find '" . DB_FILE_PGVERSION . "' in tablespace path '${strTablespacePath}'");
}
}
# Version >= 9.0 creates a special path using the version and catalog number
else
{
# Backup info will have the catalog number
my $oBackupInfo = new pgBackRest::Common::Ini(
storageRepo()->pathGet(STORAGE_REPO_BACKUP . qw{/} . FILE_BACKUP_INFO),
{bLoad => false, strContent => ${storageRepo()->get(STORAGE_REPO_BACKUP . qw{/} . FILE_BACKUP_INFO)}});
# Construct the special path
$strTablespacePath .=
'/PG_' . $oHostDbMaster->pgVersion() . qw{_} . $oBackupInfo->get(INFO_BACKUP_SECTION_DB, INFO_BACKUP_KEY_CATALOG);
# Check that path exists
if (!storageDb()->pathExists($strTablespacePath))
{
confess &log(ASSERT, "unable to find tablespace path '${strTablespacePath}'");
}
}
# Make sure there are some files in the tablespace path (exclude PG_VERSION if <= 8.4 since that was tested above)
if (grep(!/^PG\_VERSION$/i, storageDb()->list($strTablespacePath)) == 0)
{
confess &log(ASSERT, "no files found in tablespace path '${strTablespacePath}'");
}
# This table should exist to prove that the tablespace was restored. It has not been updated since it was created so it
# should not be created by any full page writes. Once it is verified to exist it can be dropped.
$oHostDbMaster->sqlSelectOneTest("select count(*) from test_exists", 0);
$oHostDbMaster->sqlExecute('drop table test_exists');
# Now it should be OK to drop database test2
if ($bTestLocal)
{