mirror of
https://github.com/postgrespro/pg_probackup.git
synced 2025-02-08 14:28:36 +02:00
Merge branch 'master' into remote_pull
This commit is contained in:
commit
4193766317
@ -584,6 +584,15 @@ do_backup_instance(void)
|
||||
strlen(" with pg_probackup"));
|
||||
pg_start_backup(label, smooth_checkpoint, ¤t);
|
||||
|
||||
/* For incremental backup check that start_lsn is not from the past */
|
||||
if (current.backup_mode != BACKUP_MODE_FULL &&
|
||||
prev_backup->start_lsn > current.start_lsn)
|
||||
elog(ERROR, "Current START LSN %X/%X is lower than START LSN %X/%X of previous backup %s. "
|
||||
"It may indicate that we are trying to backup PostgreSQL instance from the past.",
|
||||
(uint32) (current.start_lsn >> 32), (uint32) (current.start_lsn),
|
||||
(uint32) (prev_backup->start_lsn >> 32), (uint32) (prev_backup->start_lsn),
|
||||
base36enc(prev_backup->start_time));
|
||||
|
||||
/* Update running backup meta with START LSN */
|
||||
write_backup(¤t);
|
||||
|
||||
|
17
src/merge.c
17
src/merge.c
@ -81,8 +81,8 @@ do_merge(time_t backup_id)
|
||||
/* It is possible that previous merging was interrupted */
|
||||
backup->status != BACKUP_STATUS_MERGING &&
|
||||
backup->status != BACKUP_STATUS_DELETING)
|
||||
elog(ERROR, "Backup %s has status: %s",
|
||||
base36enc(backup->start_time), status2str(backup->status));
|
||||
elog(ERROR, "Backup %s has status: %s",
|
||||
base36enc(backup->start_time), status2str(backup->status));
|
||||
|
||||
if (backup->backup_mode == BACKUP_MODE_FULL)
|
||||
elog(ERROR, "Backup %s is full backup",
|
||||
@ -109,10 +109,8 @@ do_merge(time_t backup_id)
|
||||
if (full_backup->status != BACKUP_STATUS_OK &&
|
||||
/* It is possible that previous merging was interrupted */
|
||||
full_backup->status != BACKUP_STATUS_MERGING)
|
||||
elog(ERROR, "Backup %s has status: %s",
|
||||
base36enc(full_backup->start_time), status2str(full_backup->status));
|
||||
|
||||
//Assert(full_backup_idx != dest_backup_idx);
|
||||
elog(ERROR, "Backup %s has status: %s",
|
||||
base36enc(full_backup->start_time), status2str(full_backup->status));
|
||||
|
||||
/* form merge list */
|
||||
while(dest_backup->parent_backup_link)
|
||||
@ -122,8 +120,8 @@ do_merge(time_t backup_id)
|
||||
/* It is possible that previous merging was interrupted */
|
||||
dest_backup->status != BACKUP_STATUS_MERGING &&
|
||||
dest_backup->status != BACKUP_STATUS_DELETING)
|
||||
elog(ERROR, "Backup %s has status: %s",
|
||||
base36enc(dest_backup->start_time), status2str(dest_backup->status));
|
||||
elog(ERROR, "Backup %s has status: %s",
|
||||
base36enc(dest_backup->start_time), status2str(dest_backup->status));
|
||||
|
||||
parray_append(merge_list, dest_backup);
|
||||
dest_backup = dest_backup->parent_backup_link;
|
||||
@ -205,7 +203,8 @@ merge_backups(pgBackup *to_backup, pgBackup *from_backup)
|
||||
* BACKUP_STATUS_MERGING status.
|
||||
*/
|
||||
Assert(from_backup->status == BACKUP_STATUS_OK ||
|
||||
from_backup->status == BACKUP_STATUS_MERGING);
|
||||
from_backup->status == BACKUP_STATUS_MERGING ||
|
||||
from_backup->status == BACKUP_STATUS_DELETING);
|
||||
pgBackupValidate(from_backup);
|
||||
if (from_backup->status == BACKUP_STATUS_CORRUPT)
|
||||
elog(ERROR, "Interrupt merging");
|
||||
|
@ -1191,8 +1191,8 @@ XLogThreadWorker(void *arg)
|
||||
* Consider thread_arg->endSegNo and thread_arg->endpoint only if
|
||||
* they are valid.
|
||||
*/
|
||||
xlogreader->ReadRecPtr == thread_arg->endpoint &&
|
||||
nextSegNo > thread_arg->endSegNo)
|
||||
xlogreader->ReadRecPtr >= thread_arg->endpoint &&
|
||||
nextSegNo >= thread_arg->endSegNo)
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -18,7 +18,7 @@ def load_tests(loader, tests, pattern):
|
||||
# suite.addTests(loader.loadTestsFromModule(cfs_backup))
|
||||
# suite.addTests(loader.loadTestsFromModule(cfs_restore))
|
||||
# suite.addTests(loader.loadTestsFromModule(cfs_validate_backup))
|
||||
# suite.addTests(loader.loadTestsFromModule(logging))
|
||||
suite.addTests(loader.loadTestsFromModule(logging))
|
||||
suite.addTests(loader.loadTestsFromModule(compression))
|
||||
suite.addTests(loader.loadTestsFromModule(delete))
|
||||
suite.addTests(loader.loadTestsFromModule(delta))
|
||||
|
@ -422,10 +422,10 @@ class ArchiveTest(ProbackupTest, unittest.TestCase):
|
||||
set_replication=True,
|
||||
initdb_params=['--data-checksums'],
|
||||
pg_options={
|
||||
'max_wal_senders': '2',
|
||||
'archive_timeout': '10s',
|
||||
'max_wal_size': '1GB'}
|
||||
)
|
||||
'checkpoint_timeout': '30s',
|
||||
'max_wal_size': '16MB'})
|
||||
|
||||
self.init_pb(backup_dir)
|
||||
# ADD INSTANCE 'MASTER'
|
||||
self.add_instance(backup_dir, 'master', master)
|
||||
|
@ -711,14 +711,12 @@ class DeltaTest(ProbackupTest, unittest.TestCase):
|
||||
1, 0,
|
||||
"Expecting Error because we are connecting to deleted database"
|
||||
"\n Output: {0} \n CMD: {1}".format(
|
||||
repr(self.output), self.cmd)
|
||||
)
|
||||
repr(self.output), self.cmd))
|
||||
except QueryException as e:
|
||||
self.assertTrue(
|
||||
'FATAL: database "db1" does not exist' in e.message,
|
||||
'\n Unexpected Error Message: {0}\n CMD: {1}'.format(
|
||||
repr(e.message), self.cmd)
|
||||
)
|
||||
repr(e.message), self.cmd))
|
||||
|
||||
# Clean after yourself
|
||||
self.del_test_dir(module_name, fname)
|
||||
@ -1305,3 +1303,53 @@ class DeltaTest(ProbackupTest, unittest.TestCase):
|
||||
|
||||
# Clean after yourself
|
||||
self.del_test_dir(module_name, fname)
|
||||
|
||||
def test_delta_backup_from_past(self):
|
||||
"""
|
||||
make node, take FULL stream backup, take DELTA stream backup,
|
||||
restore FULL backup, try to take second DELTA stream backup
|
||||
"""
|
||||
fname = self.id().split('.')[3]
|
||||
node = self.make_simple_node(
|
||||
base_dir=os.path.join(module_name, fname, 'node'),
|
||||
initdb_params=['--data-checksums'])
|
||||
|
||||
backup_dir = os.path.join(self.tmp_path, module_name, fname, 'backup')
|
||||
self.init_pb(backup_dir)
|
||||
self.add_instance(backup_dir, 'node', node)
|
||||
node.slow_start()
|
||||
|
||||
backup_id = self.backup_node(
|
||||
backup_dir, 'node', node, options=['--stream'])
|
||||
|
||||
node.pgbench_init(scale=3)
|
||||
|
||||
# First DELTA
|
||||
self.backup_node(
|
||||
backup_dir, 'node', node,
|
||||
backup_type='delta', options=['--stream'])
|
||||
|
||||
# Restore FULL backup
|
||||
node.cleanup()
|
||||
self.restore_node(backup_dir, 'node', node, backup_id=backup_id)
|
||||
node.slow_start()
|
||||
|
||||
# Second DELTA backup
|
||||
try:
|
||||
self.backup_node(
|
||||
backup_dir, 'node', node,
|
||||
backup_type='delta', options=['--stream'])
|
||||
# we should die here because exception is what we expect to happen
|
||||
self.assertEqual(
|
||||
1, 0,
|
||||
"Expecting Error because we are backing up an instance from the past"
|
||||
"\n Output: {0} \n CMD: {1}".format(
|
||||
repr(self.output), self.cmd))
|
||||
except QueryException as e:
|
||||
self.assertTrue(
|
||||
'Insert error message' in e.message,
|
||||
'\n Unexpected Error Message: {0}\n CMD: {1}'.format(
|
||||
repr(e.message), self.cmd))
|
||||
|
||||
# Clean after yourself
|
||||
self.del_test_dir(module_name, fname)
|
||||
|
@ -39,7 +39,7 @@ pg_probackup - utility to manage backup/recovery of PostgreSQL database.
|
||||
[--log-directory=log-directory]
|
||||
[--log-rotation-size=log-rotation-size]
|
||||
[--log-rotation-age=log-rotation-age]
|
||||
[--delete-expired] [--delete-wal]
|
||||
[--delete-expired] [--delete-wal] [--merge-expired]
|
||||
[--retention-redundancy=retention-redundancy]
|
||||
[--retention-window=retention-window]
|
||||
[--compress]
|
||||
@ -51,16 +51,19 @@ pg_probackup - utility to manage backup/recovery of PostgreSQL database.
|
||||
[--master-port=port] [--master-user=user_name]
|
||||
[--replica-timeout=timeout]
|
||||
[--skip-block-validation]
|
||||
[--external-dirs=external-directory-path]
|
||||
|
||||
pg_probackup restore -B backup-path --instance=instance_name
|
||||
[-D pgdata-path] [-i backup-id] [--progress]
|
||||
[-D pgdata-path] [-i backup-id] [-j num-threads]
|
||||
[--time=time|--xid=xid|--lsn=lsn [--inclusive=boolean]]
|
||||
[--timeline=timeline] [-T OLDDIR=NEWDIR]
|
||||
[--timeline=timeline] [-T OLDDIR=NEWDIR] [--progress]
|
||||
[--external-mapping=OLDDIR=NEWDIR]
|
||||
[--immediate] [--recovery-target-name=target-name]
|
||||
[--recovery-target-action=pause|promote|shutdown]
|
||||
[--restore-as-replica]
|
||||
[--no-validate]
|
||||
[--skip-block-validation]
|
||||
[--skip-external-dirs]
|
||||
|
||||
pg_probackup validate -B backup-path [--instance=instance_name]
|
||||
[-i backup-id] [--progress] [-j num-threads]
|
||||
@ -74,10 +77,11 @@ pg_probackup - utility to manage backup/recovery of PostgreSQL database.
|
||||
[--format=format]
|
||||
|
||||
pg_probackup delete -B backup-path --instance=instance_name
|
||||
[--wal] [-i backup-id | --expired]
|
||||
[--wal] [-i backup-id | --expired | --merge-expired]
|
||||
[--dry-run]
|
||||
|
||||
pg_probackup merge -B backup-path --instance=instance_name
|
||||
-i backup-id
|
||||
-i backup-id [--progress] [-j num-threads]
|
||||
|
||||
pg_probackup add-instance -B backup-path -D pgdata-path
|
||||
--instance=instance_name
|
||||
|
@ -1197,7 +1197,7 @@ class MergeTest(ProbackupTest, unittest.TestCase):
|
||||
|
||||
def test_continue_failed_merge_2(self):
|
||||
"""
|
||||
Check that failed MERGE on delete can`t be continued
|
||||
Check that failed MERGE on delete can be continued
|
||||
"""
|
||||
fname = self.id().split('.')[3]
|
||||
backup_dir = os.path.join(self.tmp_path, module_name, fname, 'backup')
|
||||
@ -1253,6 +1253,8 @@ class MergeTest(ProbackupTest, unittest.TestCase):
|
||||
|
||||
backup_id_deleted = self.show_pb(backup_dir, "node")[1]["id"]
|
||||
|
||||
# TODO check that full backup has meta info is equal to DELETTING
|
||||
|
||||
# Try to continue failed MERGE
|
||||
self.merge_backup(backup_dir, "node", backup_id)
|
||||
# Clean after yourself
|
||||
|
@ -141,10 +141,10 @@ class ReplicaTest(ProbackupTest, unittest.TestCase):
|
||||
set_replication=True,
|
||||
initdb_params=['--data-checksums'],
|
||||
pg_options={
|
||||
'wal_level': 'replica',
|
||||
'max_wal_senders': '2',
|
||||
'archive_timeout': '10s'}
|
||||
)
|
||||
'archive_timeout': '10s',
|
||||
'checkpoint_timeout': '30s',
|
||||
'max_wal_size': '16MB'})
|
||||
|
||||
self.init_pb(backup_dir)
|
||||
self.add_instance(backup_dir, 'master', master)
|
||||
self.set_archiving(backup_dir, 'master', master)
|
||||
|
Loading…
x
Reference in New Issue
Block a user