Skip to content

Commit 5529410

Browse files
gamefienddaxaminmanue1chuckp22
authored
Incremental MySQL Backups and Restores (#366)
Implementing incremental mysql backups for 3.10 Co-authored-by: Dax Amin <[email protected]> Co-authored-by: Manuel Bergler <[email protected]> Co-authored-by: Chuck Pathanjali <[email protected]>
1 parent de185ef commit 5529410

12 files changed

+705
-31
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
11
/backup.config
22
/data
33
/dist
4+
dash
5+
parallel

bin/ghe-backup

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,10 @@ while true; do
2727
export GHE_VERBOSE=true
2828
shift
2929
;;
30+
-i|--incremental)
31+
export GHE_INCREMENTAL=true
32+
shift
33+
;;
3034
-*)
3135
echo "Error: invalid argument: '$1'" 1>&2
3236
exit 1
@@ -173,17 +177,34 @@ if [ -f ../in-progress ]; then
173177
fi
174178
fi
175179

180+
# Perform a host connection check and establish the remote appliance version.
181+
# The version is available in the GHE_REMOTE_VERSION variable and also written
182+
# to a version file in the snapshot directory itself.
183+
ghe_remote_version_required
184+
echo "$GHE_REMOTE_VERSION" > version
185+
186+
# check that incremental settings are valid if set
187+
is_inc=$(is_incremental_backup_feature_on)
188+
189+
if [ "$is_inc" = true ]; then
190+
if [ "$GHE_VERSION_MAJOR" -lt 3 ] && [ "$GHE_VERSION_MINOR" -lt 10 ]; then
191+
log_error "Cannot only perform incremental backups on enterprise version 3.10 or higher"
192+
exit 1
193+
fi
194+
incremental_backup_check
195+
# If everything is ok, check if we have hit GHE_MAX_INCREMENTAL_BACKUPS, performing pruning actions if necessary
196+
check_for_incremental_max_backups
197+
# initialize incremental backup if it hasn't been done yet
198+
incremental_backup_init
199+
fi
200+
176201
echo "$GHE_SNAPSHOT_TIMESTAMP $$" > ../in-progress
177202
echo "$GHE_SNAPSHOT_TIMESTAMP $$" > "${GHE_DATA_DIR}/in-progress-backup"
178203

179204
START_TIME=$(date +%s)
180205
log_info "Starting backup of $GHE_HOSTNAME with backup-utils v$BACKUP_UTILS_VERSION in snapshot $GHE_SNAPSHOT_TIMESTAMP"
181206

182-
# Perform a host connection check and establish the remote appliance version.
183-
# The version is available in the GHE_REMOTE_VERSION variable and also written
184-
# to a version file in the snapshot directory itself.
185-
ghe_remote_version_required
186-
echo "$GHE_REMOTE_VERSION" > version
207+
187208

188209
if [ -n "$GHE_ALLOW_REPLICA_BACKUP" ]; then
189210
echo "Warning: backing up a high availability replica may result in inconsistent or unreliable backups."

bin/ghe-restore

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,10 @@ while true; do
7171
export GHE_VERBOSE=true
7272
shift
7373
;;
74+
-i|--incremental)
75+
export GHE_INCREMENTAL=true
76+
shift
77+
;;
7478
-*)
7579
echo "Error: invalid argument: '$1'" 1>&2
7680
exit 1
@@ -321,6 +325,21 @@ echo "$PROGRESS" > /tmp/backup-utils-progress
321325
START_TIME=$(date +%s)
322326
log_info "Starting restore of $GHE_HOSTNAME with backup-utils v$BACKUP_UTILS_VERSION from snapshot $GHE_RESTORE_SNAPSHOT"
323327

328+
if [ "$GHE_INCREMENTAL" ]; then
329+
log_info "Incremental restore from snapshot $GHE_RESTORE_SNAPSHOT"
330+
# If we see 'inc_previous' prepended to the snapshot name, then
331+
# we set $INC_FULL_BACKUP and $INC_SNAPSHOT_DATA to $INC_PREVIOUS_FULL_BACKUP and
332+
# $INC_PREVIOUS_SNAPSHOT_DATA respectively. Otherwise, leave them at default setting
333+
# so that incremental restore is from current cycle
334+
if [[ "$GHE_RESTORE_SNAPSHOT" =~ ^inc_previous ]]; then
335+
INC_FULL_BACKUP=$INC_PREVIOUS_FULL_BACKUP
336+
INC_SNAPSHOT_DATA=$INC_PREVIOUS_SNAPSHOT_DATA
337+
log_info "Incremental restore from previous cycle snapshot. Using $INC_FULL_BACKUP"
338+
log_info "Incremental restore from previous cycle snapshot. Using $INC_SNAPSHOT_DATA"
339+
fi
340+
log_info "Validating snapshot $GHE_RESTORE_SNAPSHOT"
341+
validate_inc_snapshot_data "$GHE_RESTORE_SNAPSHOT"
342+
fi
324343
ghe_remote_logger "Starting restore from $(hostname) with backup-utils v$BACKUP_UTILS_VERSION / snapshot $GHE_RESTORE_SNAPSHOT ..."
325344
# Create an in-progress-restore file to prevent simultaneous backup or restore runs
326345
echo "${START_TIME} $$" > "${GHE_DATA_DIR}/in-progress-restore"
@@ -498,6 +517,8 @@ else
498517
ghe-restore-mysql "$GHE_HOSTNAME" 1>&3
499518
fi
500519

520+
521+
501522
if ghe-ssh "$GHE_HOSTNAME" -- 'ghe-config --true app.actions.enabled'; then
502523
log_info "Stopping Actions before restoring databases ..."
503524
# We mark Actions as stopped even if the `ghe-actions-stop`
@@ -601,7 +622,7 @@ fi
601622
log_info "Restarting memcached ..." 1>&3
602623
bm_start "$(basename $0) - Restarting memcached"
603624
echo "sudo restart -q memcached 2>/dev/null || true" |
604-
ghe-ssh "$GHE_HOSTNAME" -- /bin/sh
625+
ghe-ssh "$GHE_HOSTNAME" -- /bin/sh
605626
bm_end "$(basename $0) - Restarting memcached"
606627

607628
# Prevent GitHub Connect jobs running before we've had a chance to reset

share/github-backup-utils/ghe-backup-config

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,8 @@ fi
183183
PATH="$GHE_BACKUP_ROOT/bin:$GHE_BACKUP_ROOT/share/github-backup-utils:$PATH"
184184
# shellcheck source=share/github-backup-utils/bm.sh
185185
. "$GHE_BACKUP_ROOT/share/github-backup-utils/bm.sh"
186+
# shellcheck source=share/github-backup-utils/ghe-incremental-backup-restore
187+
. "$GHE_BACKUP_ROOT/share/github-backup-utils/ghe-incremental-backup-restore"
186188
# shellcheck source=share/github-backup-utils/track-progress
187189
. "$GHE_BACKUP_ROOT/share/github-backup-utils/track-progress"
188190
# Save off GHE_HOSTNAME from the environment since we want it to override the
@@ -712,12 +714,9 @@ init-progress() {
712714
rm -f /tmp/backup-utils-progress*
713715
}
714716

717+
715718
#increase total count of progress
716719
increment-progress-total-count() {
717720
((PROGRESS_TOTAL += $1))
718721
echo "$PROGRESS_TOTAL" > /tmp/backup-utils-progress-total
719722
}
720-
721-
722-
723-

share/github-backup-utils/ghe-backup-mysql

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,14 @@ else
3333
if is_binary_backup_feature_on; then
3434
ghe-backup-mysql-binary
3535
else
36+
# if incremental backups are turned on, we can't do them with
37+
# logical backups, so we need to tell the user and exit
38+
is_inc=$(is_incremental_backup_feature_on)
39+
if [ $is_inc = true ]; then
40+
log_warn "Incremental backups are configured on the target environment."
41+
log_warn "Incremental backup is not supported with a logical MySQL backup. Please disable incremental backups with 'ghe-config mysql.backup.incremental false'"
42+
exit 1
43+
fi
3644
ghe-backup-mysql-logical
3745
fi
3846
fi

share/github-backup-utils/ghe-backup-mysql-binary

Lines changed: 41 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,45 @@ bm_start "$(basename $0)"
1616
ghe_remote_version_required "$GHE_HOSTNAME"
1717

1818
log_verbose "Backing up MySQL database using binary backup strategy ..."
19-
20-
echo "set -o pipefail; ghe-export-mysql" |
21-
ghe-ssh "$GHE_HOSTNAME" -- /bin/bash > "$GHE_SNAPSHOT_DIR/mysql.sql.gz"
22-
echo "NO_ADDITIONAL_COMPRESSION" > "$GHE_SNAPSHOT_DIR/mysql-binary-backup-sentinel"
23-
19+
is_inc=$(is_incremental_backup_feature_on)
20+
if [ $is_inc = true ]; then
21+
log_verbose "Incremental backups are configured on the target environment."
22+
log_info "Performing incremental backup of MySQL database ..." 1>&3
23+
INC_TYPE=$(full_or_incremental_backup)
24+
INC_LSN=""
25+
if [ "$INC_TYPE" == "full" ]; then
26+
log_info "Incremental backup type: $INC_TYPE" 1>&3
27+
INC_LSN=0 # 0 means full backup
28+
else
29+
validate_inc_snapshot_data
30+
log_info "Incremental backup type: $INC_TYPE" 1>&3
31+
INC_LSN=$(retrieve_last_lsn)
32+
fi
33+
echo "set -o pipefail; env INC_BACKUP=$INC_LSN ghe-export-mysql" |
34+
ghe-ssh "$GHE_HOSTNAME" -- /bin/bash > "$GHE_SNAPSHOT_DIR/mysql.sql.gz"
35+
echo "NO_ADDITIONAL_COMPRESSION" > "$GHE_SNAPSHOT_DIR/mysql-binary-backup-sentinel"
36+
# Ensure that we capture the xtrabackup_checkpoints file from the remote host
37+
log_info "Checking if incremental backup is part of a cluster"
38+
GET_LSN=$(get_cluster_lsn "$GHE_HOSTNAME")
39+
ghe-ssh "$GHE_HOSTNAME" "$GET_LSN" > "$GHE_SNAPSHOT_DIR/xtrabackup_checkpoints"
40+
if [ "$INC_TYPE" == "full" ]; then
41+
log_info "Adding $GHE_SNAPSHOT_DIR to the list of full backups" 1>&3
42+
update_inc_full_backup "$GHE_SNAPSHOT_DIR"
43+
else
44+
log_info "Adding $GHE_SNAPSHOT_DIR to the list of incremental backups" 1>&3
45+
update_inc_snapshot_data "$GHE_SNAPSHOT_DIR"
46+
fi
47+
bm_end "$(basename $0)"
48+
exit 0
49+
fi
50+
# if incremental backup isn't enabled, or we are performing a full backup as part of the process,
51+
# fall through and do a full backup
52+
echo "set -o pipefail; ghe-export-mysql" |
53+
ghe-ssh "$GHE_HOSTNAME" -- /bin/bash > "$GHE_SNAPSHOT_DIR/mysql.sql.gz"
54+
echo "NO_ADDITIONAL_COMPRESSION" > "$GHE_SNAPSHOT_DIR/mysql-binary-backup-sentinel"
55+
is_inc=$(is_incremental_backup_feature_on)
56+
if [ $is_inc = true ]; then
57+
update_inc_full_backup "$GHE_SNAPSHOT_DIR"
58+
fi
2459
bm_end "$(basename $0)"
60+

0 commit comments

Comments
 (0)