diff --git a/documentation/sphinx/source/backups.rst b/documentation/sphinx/source/backups.rst index 24ae05a124..01a730a6bd 100644 --- a/documentation/sphinx/source/backups.rst +++ b/documentation/sphinx/source/backups.rst @@ -244,6 +244,9 @@ The ``start`` subcommand is used to start a backup. If there is already a backu ``-s `` or ``--snapshot_interval `` Specifies the duration, in seconds, of the inconsistent snapshots written to the backup in continuous mode. The default is 864000 which is 10 days. +``--initial_snapshot_interval `` + Specifies the duration, in seconds, of the first inconsistent snapshot written to the backup. The default is 0, which means as fast as possible. + ``--partitioned_log_experimental`` Specifies the backup uses the partitioned mutation logs generated by backup workers. Since FDB version 6.3, this option is experimental and requires using fast restore for restoring the database from the generated files. The default is to use non-partitioned mutation logs generated by backup agents. diff --git a/fdbbackup/backup.actor.cpp b/fdbbackup/backup.actor.cpp index 7cf72ab517..8bb8cd5fc3 100644 --- a/fdbbackup/backup.actor.cpp +++ b/fdbbackup/backup.actor.cpp @@ -106,6 +106,7 @@ enum { // Backup constants OPT_DESTCONTAINER, OPT_SNAPSHOTINTERVAL, + OPT_INITIAL_SNAPSHOT_INTERVAL, OPT_ERRORLIMIT, OPT_NOSTOPWHENDONE, OPT_EXPIRE_BEFORE_VERSION, @@ -233,6 +234,7 @@ CSimpleOpt::SOption g_rgBackupStartOptions[] = { { OPT_USE_PARTITIONED_LOG, "--partitioned_log_experimental", SO_NONE }, { OPT_SNAPSHOTINTERVAL, "-s", SO_REQ_SEP }, { OPT_SNAPSHOTINTERVAL, "--snapshot_interval", SO_REQ_SEP }, + { OPT_INITIAL_SNAPSHOT_INTERVAL, "--initial_snapshot_interval", SO_REQ_SEP }, { OPT_TAGNAME, "-t", SO_REQ_SEP }, { OPT_TAGNAME, "--tagname", SO_REQ_SEP }, { OPT_BACKUPKEYS, "-k", SO_REQ_SEP }, @@ -1880,6 +1882,7 @@ ACTOR Future submitDBBackup(Database src, ACTOR Future submitBackup(Database db, std::string url, + int initialSnapshotIntervalSeconds, int snapshotIntervalSeconds, Standalone> backupRanges, std::string tagName, @@ -1936,6 +1939,7 @@ ACTOR Future submitBackup(Database db, else { wait(backupAgent.submitBackup(db, KeyRef(url), + initialSnapshotIntervalSeconds, snapshotIntervalSeconds, tagName, backupRanges, @@ -3213,6 +3217,8 @@ int main(int argc, char* argv[]) { std::string destinationContainer; bool describeDeep = false; bool describeTimestamps = false; + int initialSnapshotIntervalSeconds = + 0; // The initial snapshot has a desired duration of 0, meaning go as fast as possible. int snapshotIntervalSeconds = CLIENT_KNOBS->BACKUP_DEFAULT_SNAPSHOT_INTERVAL_SEC; std::string clusterFile; std::string sourceClusterFile; @@ -3467,6 +3473,7 @@ int main(int argc, char* argv[]) { modifyOptions.destURL = destinationContainer; break; case OPT_SNAPSHOTINTERVAL: + case OPT_INITIAL_SNAPSHOT_INTERVAL: case OPT_MOD_ACTIVE_INTERVAL: { const char* a = args->OptionArg(); int seconds; @@ -3478,6 +3485,8 @@ int main(int argc, char* argv[]) { if (optId == OPT_SNAPSHOTINTERVAL) { snapshotIntervalSeconds = seconds; modifyOptions.snapshotIntervalSeconds = seconds; + } else if (optId == OPT_INITIAL_SNAPSHOT_INTERVAL) { + initialSnapshotIntervalSeconds = seconds; } else if (optId == OPT_MOD_ACTIVE_INTERVAL) { modifyOptions.activeSnapshotIntervalSeconds = seconds; } @@ -3837,6 +3846,7 @@ int main(int argc, char* argv[]) { openBackupContainer(argv[0], destinationContainer); f = stopAfter(submitBackup(db, destinationContainer, + initialSnapshotIntervalSeconds, snapshotIntervalSeconds, backupKeys, tagName, diff --git a/fdbclient/BackupAgent.actor.h b/fdbclient/BackupAgent.actor.h index fb8f6b1564..b29cee2a12 100644 --- a/fdbclient/BackupAgent.actor.h +++ b/fdbclient/BackupAgent.actor.h @@ -357,6 +357,7 @@ public: Future submitBackup(Reference tr, Key outContainer, + int initialSnapshotIntervalSeconds, int snapshotIntervalSeconds, std::string tagName, Standalone> backupRanges, @@ -365,6 +366,7 @@ public: bool incrementalBackupOnly = false); Future submitBackup(Database cx, Key outContainer, + int initialSnapshotIntervalSeconds, int snapshotIntervalSeconds, std::string tagName, Standalone> backupRanges, @@ -374,6 +376,7 @@ public: return runRYWTransactionFailIfLocked(cx, [=](Reference tr) { return submitBackup(tr, outContainer, + initialSnapshotIntervalSeconds, snapshotIntervalSeconds, tagName, backupRanges, @@ -404,7 +407,8 @@ public: Future getStatus(Database cx, bool showErrors, std::string tagName); Future getStatusJSON(Database cx, std::string tagName); - Future> getLastRestorable(Reference tr, Key tagName, + Future> getLastRestorable(Reference tr, + Key tagName, bool snapshot = false); void setLastRestorable(Reference tr, Key tagName, Version version); @@ -835,6 +839,11 @@ public: typedef KeyBackedMap RangeDispatchMapT; RangeDispatchMapT snapshotRangeDispatchMap() { return configSpace.pack(LiteralStringRef(__FUNCTION__)); } + // Interval to use for the first (initial) snapshot. + KeyBackedProperty initialSnapshotIntervalSeconds() { + return configSpace.pack(LiteralStringRef(__FUNCTION__)); + } + // Interval to use for determining the target end version for new snapshots KeyBackedProperty snapshotIntervalSeconds() { return configSpace.pack(LiteralStringRef(__FUNCTION__)); } @@ -864,8 +873,9 @@ public: Future beginVersion = tr->getReadVersion(); Future defaultInterval = 0; - if (intervalSeconds < 0) + if (intervalSeconds < 0) { defaultInterval = copy.snapshotIntervalSeconds().getOrThrow(tr); + } // Make sure read version and possibly the snapshot interval value are ready, then clear/init the snapshot // config members diff --git a/fdbclient/FileBackupAgent.actor.cpp b/fdbclient/FileBackupAgent.actor.cpp index e7da8fbf58..4e9c2b7228 100644 --- a/fdbclient/FileBackupAgent.actor.cpp +++ b/fdbclient/FileBackupAgent.actor.cpp @@ -2777,9 +2777,9 @@ struct StartFullBackupTaskFunc : BackupTaskFuncBase { state Reference backupFinished = futureBucket->future(tr); - // Initialize the initial snapshot and create tasks to continually write logs and snapshots - // The initial snapshot has a desired duration of 0, meaning go as fast as possible. - wait(config.initNewSnapshot(tr, 0)); + // Initialize the initial snapshot and create tasks to continually write logs and snapshots. + state Optional initialSnapshotIntervalSeconds = wait(config.initialSnapshotIntervalSeconds().get(tr)); + wait(config.initNewSnapshot(tr, initialSnapshotIntervalSeconds.orDefault(0))); // Using priority 1 for both of these to at least start both tasks soon // Do not add snapshot task if we only want the incremental backup @@ -4442,6 +4442,7 @@ public: ACTOR static Future submitBackup(FileBackupAgent* backupAgent, Reference tr, Key outContainer, + int initialSnapshotIntervalSeconds, int snapshotIntervalSeconds, std::string tagName, Standalone> backupRanges, @@ -4557,6 +4558,7 @@ public: config.backupContainer().set(tr, bc); config.stopWhenDone().set(tr, stopWhenDone); config.backupRanges().set(tr, normalizedRanges); + config.initialSnapshotIntervalSeconds().set(tr, initialSnapshotIntervalSeconds); config.snapshotIntervalSeconds().set(tr, snapshotIntervalSeconds); config.partitionedLogEnabled().set(tr, partitionedLog); config.incrementalBackupOnly().set(tr, incrementalBackupOnly); @@ -5183,7 +5185,8 @@ public: } ACTOR static Future> getLastRestorable(FileBackupAgent* backupAgent, - Reference tr, Key tagName, + Reference tr, + Key tagName, bool snapshot) { tr->setOption(FDBTransactionOptions::ACCESS_SYSTEM_KEYS); tr->setOption(FDBTransactionOptions::LOCK_AWARE); @@ -5544,6 +5547,7 @@ Future FileBackupAgent::waitRestore(Database cx, Key tagName, boo Future FileBackupAgent::submitBackup(Reference tr, Key outContainer, + int initialSnapshotIntervalSeconds, int snapshotIntervalSeconds, std::string tagName, Standalone> backupRanges, @@ -5553,6 +5557,7 @@ Future FileBackupAgent::submitBackup(Reference return FileBackupAgentImpl::submitBackup(this, tr, outContainer, + initialSnapshotIntervalSeconds, snapshotIntervalSeconds, tagName, backupRanges, @@ -5577,7 +5582,8 @@ Future FileBackupAgent::getStatusJSON(Database cx, std::string tagN return FileBackupAgentImpl::getStatusJSON(this, cx, tagName); } -Future> FileBackupAgent::getLastRestorable(Reference tr, Key tagName, +Future> FileBackupAgent::getLastRestorable(Reference tr, + Key tagName, bool snapshot) { return FileBackupAgentImpl::getLastRestorable(this, tr, tagName, snapshot); } diff --git a/fdbserver/workloads/AtomicRestore.actor.cpp b/fdbserver/workloads/AtomicRestore.actor.cpp index fb121bcc28..33412123f2 100644 --- a/fdbserver/workloads/AtomicRestore.actor.cpp +++ b/fdbserver/workloads/AtomicRestore.actor.cpp @@ -93,6 +93,7 @@ struct AtomicRestoreWorkload : TestWorkload { try { wait(backupAgent.submitBackup(cx, StringRef(backupContainer), + deterministicRandom()->randomInt(0, 60), deterministicRandom()->randomInt(0, 100), BackupAgentBase::getDefaultTagName(), self->backupRanges, diff --git a/fdbserver/workloads/BackupAndParallelRestoreCorrectness.actor.cpp b/fdbserver/workloads/BackupAndParallelRestoreCorrectness.actor.cpp index 9e8efe2937..cbbe52f64a 100644 --- a/fdbserver/workloads/BackupAndParallelRestoreCorrectness.actor.cpp +++ b/fdbserver/workloads/BackupAndParallelRestoreCorrectness.actor.cpp @@ -222,6 +222,7 @@ struct BackupAndParallelRestoreCorrectnessWorkload : TestWorkload { try { wait(backupAgent->submitBackup(cx, StringRef(backupContainer), + deterministicRandom()->randomInt(0, 60), deterministicRandom()->randomInt(0, 100), tag.toString(), backupRanges, @@ -477,6 +478,7 @@ struct BackupAndParallelRestoreCorrectnessWorkload : TestWorkload { // the configuration to disable backup workers before restore. extraBackup = backupAgent.submitBackup(cx, LiteralStringRef("file://simfdb/backups/"), + deterministicRandom()->randomInt(0, 60), deterministicRandom()->randomInt(0, 100), self->backupTag.toString(), self->backupRanges, diff --git a/fdbserver/workloads/BackupCorrectness.actor.cpp b/fdbserver/workloads/BackupCorrectness.actor.cpp index 4a57d399fe..a6ad2c783b 100644 --- a/fdbserver/workloads/BackupCorrectness.actor.cpp +++ b/fdbserver/workloads/BackupCorrectness.actor.cpp @@ -248,6 +248,7 @@ struct BackupAndRestoreCorrectnessWorkload : TestWorkload { try { wait(backupAgent->submitBackup(cx, StringRef(backupContainer), + deterministicRandom()->randomInt(0, 60), deterministicRandom()->randomInt(0, 100), tag.toString(), backupRanges, @@ -497,6 +498,7 @@ struct BackupAndRestoreCorrectnessWorkload : TestWorkload { try { extraBackup = backupAgent.submitBackup(cx, LiteralStringRef("file://simfdb/backups/"), + deterministicRandom()->randomInt(0, 60), deterministicRandom()->randomInt(0, 100), self->backupTag.toString(), self->backupRanges, diff --git a/fdbserver/workloads/BackupToBlob.actor.cpp b/fdbserver/workloads/BackupToBlob.actor.cpp index 374b0d7f5d..5b94e4d771 100644 --- a/fdbserver/workloads/BackupToBlob.actor.cpp +++ b/fdbserver/workloads/BackupToBlob.actor.cpp @@ -29,6 +29,7 @@ struct BackupToBlobWorkload : TestWorkload { double backupAfter; Key backupTag; Standalone backupURL; + int initSnapshotInterval = 0; int snapshotInterval = 100000; static constexpr const char* DESCRIPTION = "BackupToBlob"; @@ -59,8 +60,12 @@ struct BackupToBlobWorkload : TestWorkload { backupRanges.push_back_deep(backupRanges.arena(), normalKeys); wait(delay(self->backupAfter)); - wait(backupAgent.submitBackup( - cx, self->backupURL, self->snapshotInterval, self->backupTag.toString(), backupRanges)); + wait(backupAgent.submitBackup(cx, + self->backupURL, + self->initSnapshotInterval, + self->snapshotInterval, + self->backupTag.toString(), + backupRanges)); EBackupState backupStatus = wait(backupAgent.waitBackup(cx, self->backupTag.toString(), true)); TraceEvent("BackupToBlob_BackupStatus").detail("Status", BackupAgentBase::getStateText(backupStatus)); return Void(); diff --git a/fdbserver/workloads/IncrementalBackup.actor.cpp b/fdbserver/workloads/IncrementalBackup.actor.cpp index 52aeae2859..8c4b20a07a 100644 --- a/fdbserver/workloads/IncrementalBackup.actor.cpp +++ b/fdbserver/workloads/IncrementalBackup.actor.cpp @@ -151,7 +151,7 @@ struct IncrementalBackupWorkload : TestWorkload { TraceEvent("IBackupSubmitAttempt"); try { wait(self->backupAgent.submitBackup( - cx, self->backupDir, 1e8, self->tag.toString(), backupRanges, false, false, true)); + cx, self->backupDir, 0, 1e8, self->tag.toString(), backupRanges, false, false, true)); } catch (Error& e) { TraceEvent("IBackupSubmitError").error(e); if (e.code() != error_code_backup_duplicate) { diff --git a/fdbserver/workloads/SubmitBackup.actor.cpp b/fdbserver/workloads/SubmitBackup.actor.cpp index e468664514..6dbc58abf8 100644 --- a/fdbserver/workloads/SubmitBackup.actor.cpp +++ b/fdbserver/workloads/SubmitBackup.actor.cpp @@ -33,6 +33,7 @@ struct SubmitBackupWorkload final : TestWorkload { Standalone backupDir; Standalone tag; double delayFor; + int initSnapshotInterval; int snapshotInterval; bool stopWhenDone; bool incremental; @@ -41,6 +42,7 @@ struct SubmitBackupWorkload final : TestWorkload { backupDir = getOption(options, LiteralStringRef("backupDir"), LiteralStringRef("file://simfdb/backups/")); tag = getOption(options, LiteralStringRef("tag"), LiteralStringRef("default")); delayFor = getOption(options, LiteralStringRef("delayFor"), 10.0); + initSnapshotInterval = getOption(options, LiteralStringRef("initSnapshotInterval"), 0); snapshotInterval = getOption(options, LiteralStringRef("snapshotInterval"), 1e8); stopWhenDone = getOption(options, LiteralStringRef("stopWhenDone"), true); incremental = getOption(options, LiteralStringRef("incremental"), false); @@ -55,6 +57,7 @@ struct SubmitBackupWorkload final : TestWorkload { try { wait(self->backupAgent.submitBackup(cx, self->backupDir, + self->initSnapshotInterval, self->snapshotInterval, self->tag.toString(), backupRanges,