Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 46 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,51 @@ gprestore --timestamp <YYYYMMDDHHMMSS>

Run `--help` with either command for a complete list of options.

### Standby history database synchronization

After a successful backup, `gpbackup` automatically copies a consistent
snapshot of the coordinator's `gpbackup_history.db` to an up standby
coordinator. Synchronization starts only after the final `Success` history row
has been written and the local SQLite connection has been closed.

This synchronization is best effort. If no up standby exists, synchronization
is skipped. If discovery, snapshot creation, transfer, or installation fails,
`gpbackup` logs a warning but keeps the successful backup exit status. A
failed or terminated backup is not synchronized. Synchronization also does not
run when `--no-history` is used or when the final history update fails. Use
`--no-history-sync-standby` to keep writing local history while disabling
standby synchronization for one backup:

```bash
gpbackup --dbname <your_db_name> --no-history-sync-standby
```

The synchronization process:

1. Takes a non-waiting lock next to the canonical source database.
2. Creates a consistent SQLite snapshot with `VACUUM INTO` and accepts it only
when `PRAGMA quick_check` returns `ok`.
3. Transfers the snapshot with `rsync -p` to a unique temporary file in the
standby coordinator data directory.
4. Preserves the existing standby file's owner, group, and mode when it
exists, then atomically renames the temporary file to
`gpbackup_history.db`.

The host running `gpbackup` must have `ssh` and `rsync`, and the current OS
user must have non-interactive SSH access to the standby host. That user must
be able to create files in the standby coordinator data directory and preserve
the destination file's ownership and permissions. The cluster must expose an
up standby in `gp_segment_configuration`.

The atomic rename prevents readers from observing a partially copied database,
but it is not a failover coordination mechanism. A coordinator role change
during synchronization can race with discovery and installation. Processes
that already have the old standby database open continue reading that old
inode until they close and reopen it.

For automatic synchronization after history maintenance and for the strict
manual command, see [gpBackMan history synchronization](./gpbackman/README.md#standby-history-db-sync).

## Additional tools

This repository also includes the following tools:
Expand Down Expand Up @@ -196,4 +241,4 @@ the [LICENSE](./LICENSE).
## Acknowledgment

Thanks to all the Greenplum Backup contributors, more details in its [GitHub
page](https://github.com/greenplum-db/gpbackup-archive).
page](https://github.com/greenplum-db/gpbackup-archive).
4 changes: 4 additions & 0 deletions backup/backup.go
Original file line number Diff line number Diff line change
Expand Up @@ -509,6 +509,7 @@ func DoCleanup(backupFailed bool) {
// failure; in either case, update the end time to the actual value. Between our signal handler and recovering
// panics, there should be no way for gpbackup to exit that leaves the entry in the initial status.

historyUpdated := false
if !MustGetFlagBool(options.NO_HISTORY) {
var statusString string
if backupFailed {
Expand All @@ -525,9 +526,12 @@ func DoCleanup(backupFailed bool) {
historyDB.Close()
if err != nil {
gplog.Error("Unable to update history database. Error: %v", err)
} else {
historyUpdated = true
}
}
}
syncBackupHistoryToStandbyAfterCleanup(backupFailed, historyUpdated)

err := backupLockFile.Unlock()
if err != nil && backupLockFile != "" {
Expand Down
Loading
Loading