mirror of
https://github.com/pgbackrest/pgbackrest.git
synced 2025-03-03 14:52:21 +02:00
Trying to find realistic conditions where a file can be changed without the timestamp changing between backups. So far, this is the only case I can make work - it looks like adding a 1 second pause after creation of the manifest would cover this case.
This commit is contained in:
parent
59e901684d
commit
32b37335a1
@ -1463,6 +1463,130 @@ sub BackRestTestBackup_Test
|
|||||||
BackRestTestBackup_Drop();
|
BackRestTestBackup_Drop();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#-------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
# Test collision
|
||||||
|
#
|
||||||
|
# See if it is possible for a table to be written to, have stop backup run, and be written to again all in the same second.
|
||||||
|
#-------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
if ($strTest eq 'collision')
|
||||||
|
{
|
||||||
|
$iRun = 0;
|
||||||
|
my $iRunMax = 1000;
|
||||||
|
|
||||||
|
&log(INFO, "Test Backup Collision\n");
|
||||||
|
|
||||||
|
# Create the file object
|
||||||
|
my $oFile = (BackRest::File->new
|
||||||
|
(
|
||||||
|
$strStanza,
|
||||||
|
BackRestTestCommon_BackupPathGet(),
|
||||||
|
undef,
|
||||||
|
undef
|
||||||
|
))->clone();
|
||||||
|
|
||||||
|
# Create the test database
|
||||||
|
BackRestTestBackup_Create(false);
|
||||||
|
|
||||||
|
# Create the config file
|
||||||
|
BackRestTestCommon_ConfigCreate('db', # local
|
||||||
|
undef, # remote
|
||||||
|
false, # compress
|
||||||
|
false, # checksum
|
||||||
|
false, # hardlink
|
||||||
|
$iThreadMax, # thread-max
|
||||||
|
false, # archive-async
|
||||||
|
undef); # compress-async
|
||||||
|
|
||||||
|
# Create the test table
|
||||||
|
BackRestTestBackup_PgExecute("create table test_collision (id int)");
|
||||||
|
|
||||||
|
# Construct filename to test
|
||||||
|
my $strFile = BackRestTestCommon_DbCommonPathGet() . "/base";
|
||||||
|
|
||||||
|
# Get the oid of the user db
|
||||||
|
my $strSql = "select oid from pg_database where datname = 'postgres'";
|
||||||
|
my $hStatement = $hDb->prepare($strSql);
|
||||||
|
|
||||||
|
$hStatement->execute() or
|
||||||
|
confess &log(ERROR, "Unable to execute: ${strSql}");
|
||||||
|
|
||||||
|
my @oyRow = $hStatement->fetchrow_array();
|
||||||
|
$strFile .= '/' . $oyRow[0];
|
||||||
|
|
||||||
|
$hStatement->finish();
|
||||||
|
|
||||||
|
# Get the oid of the new table so we can check the file on disk
|
||||||
|
$strSql = "select oid from pg_class where relname = 'test_collision'";
|
||||||
|
$hStatement = $hDb->prepare($strSql);
|
||||||
|
|
||||||
|
$hStatement->execute() or
|
||||||
|
confess &log(ERROR, "Unable to execute: ${strSql}");
|
||||||
|
|
||||||
|
my @oyRow = $hStatement->fetchrow_array();
|
||||||
|
$strFile .= '/' . $oyRow[0];
|
||||||
|
|
||||||
|
&log(INFO, 'table filename = ' . $strFile);
|
||||||
|
|
||||||
|
$hStatement->finish();
|
||||||
|
|
||||||
|
BackRestTestBackup_PgExecute("select pg_start_backup('test');");
|
||||||
|
|
||||||
|
# File modified in the same second that the manifest is taken and file is copied
|
||||||
|
while ($iRun < $iRunMax)
|
||||||
|
{
|
||||||
|
# Increment the run, log, and decide whether this unit test should be run
|
||||||
|
if (!BackRestTestCommon_Run(++$iRun,
|
||||||
|
"mod after manifest")) {next}
|
||||||
|
|
||||||
|
my $strTestChecksum = $oFile->hash(PATH_DB_ABSOLUTE, $strFile);
|
||||||
|
|
||||||
|
# Insert a row and do a checkpoint
|
||||||
|
BackRestTestBackup_PgExecute("insert into test_collision values (1)", true);
|
||||||
|
|
||||||
|
# Stat the file to get size/modtime after the backup has started
|
||||||
|
my $strBeginChecksum = $oFile->hash(PATH_DB_ABSOLUTE, $strFile);
|
||||||
|
my $oStat = lstat($strFile);
|
||||||
|
my $lBeginSize = $oStat->size;
|
||||||
|
my $lBeginTime = $oStat->mtime;
|
||||||
|
|
||||||
|
# Sleep .5 seconds to give a reasonable amount of time for the file to be copied after the manifest was generated
|
||||||
|
sleep(.5);
|
||||||
|
|
||||||
|
# Insert another row
|
||||||
|
BackRestTestBackup_PgExecute("insert into test_collision values (1)");
|
||||||
|
|
||||||
|
# Stop backup, start a new backup
|
||||||
|
BackRestTestBackup_PgExecute("select pg_stop_backup();");
|
||||||
|
BackRestTestBackup_PgExecute("select pg_start_backup('test');");
|
||||||
|
|
||||||
|
# Stat the file to get size/modtime after the backup has restarted
|
||||||
|
my $strEndChecksum = $oFile->hash(PATH_DB_ABSOLUTE, $strFile);
|
||||||
|
$oStat = lstat($strFile);
|
||||||
|
my $lEndSize = $oStat->size;
|
||||||
|
my $lEndTime = $oStat->mtime;
|
||||||
|
|
||||||
|
# Error if the size/modtime are the same between the backups
|
||||||
|
&log(INFO, " begin size = ${lBeginSize}, time = ${lBeginTime}, hash ${strBeginChecksum} - " .
|
||||||
|
"end size = ${lEndSize}, time = ${lEndTime}, hash ${strEndChecksum} - test hash ${strTestChecksum}");
|
||||||
|
|
||||||
|
if ($lBeginSize == $lEndSize && $lBeginTime == $lEndTime &&
|
||||||
|
$strTestChecksum ne $strBeginChecksum && $strBeginChecksum ne $strEndChecksum)
|
||||||
|
{
|
||||||
|
&log(ERROR, "size and mod time are the same between backups");
|
||||||
|
$iRun = $iRunMax;
|
||||||
|
next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BackRestTestBackup_PgExecute("select pg_stop_backup();");
|
||||||
|
|
||||||
|
if (BackRestTestCommon_Cleanup())
|
||||||
|
{
|
||||||
|
&log(INFO, 'cleanup');
|
||||||
|
BackRestTestBackup_Drop();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
1;
|
1;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user