-
Notifications
You must be signed in to change notification settings - Fork 43
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: xtrabackup incremental backup for mysql (#1358)
- Loading branch information
Showing
12 changed files
with
466 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
86 changes: 86 additions & 0 deletions
86
addons/apecloud-mysql/dataprotection/xtrabackup-incremental-backup.sh
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
#!/bin/bash | ||
set -e | ||
set -o pipefail | ||
|
||
# if the script exits with a non-zero exit code, touch a file to indicate that the backup failed, | ||
# the sync progress container will check this file and exit if it exists | ||
function handle_exit() { | ||
exit_code=$? | ||
if [ $exit_code -ne 0 ]; then | ||
echo "failed with exit code $exit_code" | ||
touch "${DP_BACKUP_INFO_FILE}.exit" | ||
exit 1 | ||
fi | ||
} | ||
trap handle_exit EXIT | ||
|
||
export PATH="$PATH:$DP_DATASAFED_BIN_PATH" | ||
|
||
# 1. check parent backup name | ||
if [[ -z ${DP_PARENT_BACKUP_NAME} ]]; then | ||
echo "DP_PARENT_BACKUP_NAME is empty" | ||
exit 1 | ||
fi | ||
|
||
# 2. get parent backup lsn or download backup file | ||
mkdir -p ${DATA_DIR} | ||
PARENT_DIR=${DATA_MOUNT_DIR}/xtrabackup-parent | ||
|
||
# function get_last_lsn gets parent backup lsn from datasafed | ||
function get_last_lsn() { | ||
export DATASAFED_BACKEND_BASE_PATH="${DP_BACKUP_ROOT_PATH}/${DP_PARENT_BACKUP_NAME}/${DP_TARGET_RELATIVE_PATH}" | ||
lsnFile="${DP_PARENT_BACKUP_NAME}.lsn" | ||
if [ "$(datasafed list ${lsnFile})" == "${lsnFile}" ]; then | ||
echo "$(datasafed pull "/${lsnFile}" - | awk '{print $1}')" | ||
fi | ||
} | ||
|
||
# function download_parent_backup_file downloads the parent backup file from datasafed | ||
function download_parent_backup_file() { | ||
rm -rf ${PARENT_DIR} | ||
mkdir -p ${PARENT_DIR} && cd ${PARENT_DIR} | ||
export DATASAFED_BACKEND_BASE_PATH="${DP_BACKUP_ROOT_PATH}/${DP_PARENT_BACKUP_NAME}/${DP_TARGET_RELATIVE_PATH}" | ||
datasafed pull "${DP_PARENT_BACKUP_NAME}.xbstream" - | xbstream -x | ||
xtrabackup --decompress --remove-original --target-dir=${PARENT_DIR} | ||
} | ||
|
||
# build incremental cmd | ||
incremental_cmd="" | ||
last_lsn=$(get_last_lsn) | ||
if [ -n "${last_lsn}" ]; then | ||
incremental_cmd="--incremental-lsn=${last_lsn}" | ||
echo "create incremental backup based on parent backup lsn" | ||
else | ||
download_parent_backup_file | ||
incremental_cmd="--incremental-basedir=${PARENT_DIR}" | ||
echo "create incremental backup based on parent backup file" | ||
fi | ||
|
||
# set the datasafed backend base path for the current backup | ||
# it is equal to ${DP_BACKUP_ROOT_PATH}/${DP_BACKUP_NAME}/${DP_TARGET_RELATIVE_PATH} | ||
export DATASAFED_BACKEND_BASE_PATH="$DP_BACKUP_BASE_PATH" | ||
# compatible with version 0.6 | ||
if [ -f ${DATA_DIR}/mysql-bin.index ]; then | ||
echo "" | datasafed push - "apecloud-mysql.old" | ||
fi | ||
|
||
# 3. do incremental xtrabackup | ||
TMP_DIR=${DATA_MOUNT_DIR}/xtrabackup-temp | ||
mkdir -p ${TMP_DIR} | ||
START_TIME=$(date -u '+%Y-%m-%dT%H:%M:%SZ') | ||
xtrabackup --compress=zstd --backup --safe-slave-backup --slave-info --stream=xbstream \ | ||
--host=${DP_DB_HOST} --port=${DP_DB_PORT} \ | ||
--user=${DP_DB_USER} --password=${DP_DB_PASSWORD} \ | ||
--datadir=${DATA_DIR} ${incremental_cmd} \ | ||
2> >(tee ${TMP_DIR}/xtrabackup.log >&2) \ | ||
| datasafed push - "/${DP_BACKUP_NAME}.xbstream" | ||
# record lsn for incremental backups | ||
cat "${TMP_DIR}/xtrabackup.log" \ | ||
| grep "The latest check point (for incremental)" \ | ||
| awk -F"'" '{print $2}' \ | ||
| datasafed push - "/${DP_BACKUP_NAME}.lsn" | ||
STOP_TIME=$(date -u '+%Y-%m-%dT%H:%M:%SZ') | ||
TOTAL_SIZE=$(datasafed stat / | grep TotalSize | awk '{print $2}') | ||
echo "{\"totalSize\":\"$TOTAL_SIZE\",\"timeRange\":{\"start\":\"${START_TIME}\",\"end\":\"${STOP_TIME}\"}}" >"${DP_BACKUP_INFO_FILE}" | ||
rm -rf ${PARENT_DIR} | ||
rm -rf ${TMP_DIR} |
64 changes: 64 additions & 0 deletions
64
addons/apecloud-mysql/dataprotection/xtrabackup-incremental-restore.sh
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
#!/bin/bash | ||
set -e | ||
set -o pipefail | ||
export PATH="$PATH:$DP_DATASAFED_BIN_PATH" | ||
|
||
# function change_backend_path changes the DATASAFED_BACKEND_BASE_PATH by backup name | ||
function change_backend_path() { | ||
backup_name=$1 | ||
export DATASAFED_BACKEND_BASE_PATH="${DP_BACKUP_ROOT_PATH}/${backup_name}/${DP_TARGET_RELATIVE_PATH}" | ||
} | ||
|
||
# function download_backup_file downloads a backup file to a local target directory | ||
function download_backup_file() { | ||
backup_name=$1 | ||
local_target_dir=$2 | ||
mkdir -p ${local_target_dir} && cd ${local_target_dir} | ||
change_backend_path "${backup_name}" | ||
datasafed pull "${backup_name}.xbstream" - | xbstream -x | ||
xtrabackup --decompress --remove-original --target-dir=${local_target_dir} | ||
} | ||
|
||
# 1. check base backup name | ||
if [[ -z ${DP_BASE_BACKUP_NAME} ]]; then | ||
echo "DP_BASE_BACKUP_NAME is empty" | ||
exit 1 | ||
fi | ||
|
||
# 2. download backup files | ||
# download base backup file | ||
mkdir -p ${DATA_DIR} | ||
BASE_DIR=${DATA_MOUNT_DIR}/xtrabackup-base | ||
download_backup_file "${DP_BASE_BACKUP_NAME}" "${BASE_DIR}" | ||
# download parent backup files | ||
if [ -n "${DP_ANCESTOR_INCREMENTAL_BACKUP_NAMES}" ]; then | ||
read -r -a ANCESTOR_INCREMENTAL_BACKUP_NAMES <<< "${DP_ANCESTOR_INCREMENTAL_BACKUP_NAMES//,/ }" | ||
fi | ||
INCS_DIR=${DATA_MOUNT_DIR}/xtrabackup-incs | ||
mkdir -p ${INCS_DIR} | ||
for parent_name in "${ANCESTOR_INCREMENTAL_BACKUP_NAMES[@]}"; do | ||
download_backup_file "${parent_name}" "${INCS_DIR}/${parent_name}" | ||
done | ||
# download target backup file | ||
download_backup_file "${DP_BACKUP_NAME}" "${INCS_DIR}/${DP_BACKUP_NAME}" | ||
|
||
old_signal="apecloud-mysql.old" | ||
log_bin=${LOG_BIN} | ||
if [ "$(datasafed list ${old_signal})" == "${old_signal}" ]; then | ||
log_bin="${DATA_DIR}/mysql-bin" | ||
fi | ||
|
||
# 3. prepare data | ||
xtrabackup --prepare --apply-log-only --target-dir=${BASE_DIR} | ||
for parent_name in "${ANCESTOR_INCREMENTAL_BACKUP_NAMES[@]}"; do | ||
xtrabackup --prepare --apply-log-only --target-dir=${BASE_DIR} --incremental-dir=${INCS_DIR}/${parent_name} | ||
done | ||
xtrabackup --prepare --target-dir=${BASE_DIR} --incremental-dir=${INCS_DIR}/${DP_BACKUP_NAME} | ||
|
||
# 4. restore | ||
xtrabackup --move-back --target-dir=${BASE_DIR} --datadir=${DATA_DIR}/ --log-bin=${log_bin} | ||
touch ${DATA_DIR}/${SIGNAL_FILE} | ||
rm -rf ${BASE_DIR} | ||
rm -rf ${INCS_DIR} | ||
chmod -R 0777 ${DATA_DIR} | ||
echo "Restore completed!" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
42 changes: 42 additions & 0 deletions
42
addons/apecloud-mysql/templates/actionset-incremental.yaml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
apiVersion: dataprotection.kubeblocks.io/v1alpha1 | ||
kind: ActionSet | ||
metadata: | ||
name: {{ include "apecloud-mysql.xtrabackupIncActionSetName" . }} | ||
labels: | ||
clusterdefinition.kubeblocks.io/name: apecloud-mysql | ||
spec: | ||
backupType: Incremental | ||
env: | ||
- name: DATA_DIR | ||
value: {{ .Values.mysqlConfigs.dataDir }} | ||
- name: LOG_BIN | ||
value: {{ .Values.mysqlConfigs.logBin }} | ||
- name: DP_DB_PORT | ||
value: "3306" | ||
- name: DATA_MOUNT_DIR | ||
value: {{ .Values.mysqlConfigs.dataMountPath }} | ||
- name: SIGNAL_FILE | ||
value: .xtrabackup_restore_new_cluster | ||
backup: | ||
preBackup: [] | ||
postBackup: [] | ||
backupData: | ||
image: {{ include "apecloud-mysql.bakcupToolImage" . }} | ||
runOnTargetPodNode: true | ||
command: | ||
- bash | ||
- -c | ||
- | | ||
{{- .Files.Get "dataprotection/xtrabackup-incremental-backup.sh" | nindent 8 }} | ||
syncProgress: | ||
enabled: true | ||
intervalSeconds: 5 | ||
restore: | ||
prepareData: | ||
image: {{ include "apecloud-mysql.bakcupToolImage" . }} | ||
command: | ||
- sh | ||
- -c | ||
- | | ||
{{- .Files.Get "dataprotection/xtrabackup-incremental-restore.sh" | nindent 8 }} | ||
postReady: [] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
91 changes: 91 additions & 0 deletions
91
addons/mysql/dataprotection/xtrabackup-incremental-backup.sh
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
#!/bin/bash | ||
set -e | ||
set -o pipefail | ||
|
||
# if the script exits with a non-zero exit code, touch a file to indicate that the backup failed, | ||
# the sync progress container will check this file and exit if it exists | ||
function handle_exit() { | ||
exit_code=$? | ||
if [ $exit_code -ne 0 ]; then | ||
echo "failed with exit code $exit_code" | ||
touch "${DP_BACKUP_INFO_FILE}.exit" | ||
exit 1 | ||
fi | ||
} | ||
trap handle_exit EXIT | ||
|
||
export PATH="$PATH:$DP_DATASAFED_BIN_PATH" | ||
|
||
# 1. check parent backup name | ||
if [[ -z ${DP_PARENT_BACKUP_NAME} ]]; then | ||
echo "DP_PARENT_BACKUP_NAME is empty" | ||
exit 1 | ||
fi | ||
|
||
# 2. get parent backup lsn or download backup file | ||
mkdir -p ${DATA_DIR} | ||
PARENT_DIR=${MYSQL_DIR}/xtrabackup-parent | ||
|
||
# function get_last_lsn gets parent backup lsn from datasafed | ||
function get_last_lsn() { | ||
export DATASAFED_BACKEND_BASE_PATH="${DP_BACKUP_ROOT_PATH}/${DP_PARENT_BACKUP_NAME}/${DP_TARGET_RELATIVE_PATH}" | ||
lsnFile="${DP_PARENT_BACKUP_NAME}.lsn" | ||
if [ "$(datasafed list ${lsnFile})" == "${lsnFile}" ]; then | ||
echo "$(datasafed pull "/${lsnFile}" - | awk '{print $1}')" | ||
fi | ||
} | ||
|
||
# function download_parent_backup_file downloads the parent backup file from datasafed | ||
function download_parent_backup_file() { | ||
rm -rf ${PARENT_DIR} | ||
mkdir -p ${PARENT_DIR} && cd ${PARENT_DIR} | ||
export DATASAFED_BACKEND_BASE_PATH="${DP_BACKUP_ROOT_PATH}/${DP_PARENT_BACKUP_NAME}/${DP_TARGET_RELATIVE_PATH}" | ||
xbstreamFile="${DP_PARENT_BACKUP_NAME}.xbstream.zst" | ||
if [ "$(datasafed list ${xbstreamFile})" == "${xbstreamFile}" ]; then | ||
datasafed pull -d zstd-fastest "${xbstreamFile}" - | xbstream -x | ||
else | ||
datasafed pull "${DP_PARENT_BACKUP_NAME}.xbstream" - | xbstream -x | ||
fi | ||
xtrabackup --decompress --remove-original --target-dir=${PARENT_DIR} | ||
} | ||
|
||
# build incremental cmd | ||
incremental_cmd="" | ||
last_lsn=$(get_last_lsn) | ||
if [ -n "${last_lsn}" ]; then | ||
incremental_cmd="--incremental-lsn=${last_lsn}" | ||
echo "create incremental backup based on parent backup lsn" | ||
else | ||
download_parent_backup_file | ||
incremental_cmd="--incremental-basedir=${PARENT_DIR}" | ||
echo "create incremental backup based on parent backup file" | ||
fi | ||
|
||
# set the datasafed backend base path for the current backup | ||
# it is equal to ${DP_BACKUP_ROOT_PATH}/${DP_BACKUP_NAME}/${DP_TARGET_RELATIVE_PATH} | ||
export DATASAFED_BACKEND_BASE_PATH="$DP_BACKUP_BASE_PATH" | ||
|
||
# compatible with version 2.4 | ||
lock_per_table_ddl="" | ||
if [ "${IMAGE_TAG}" == "2.4" ]; then | ||
lock_per_table_ddl="--lock-ddl-per-table" | ||
fi | ||
|
||
# 3. do incremental xtrabackup | ||
TMP_DIR=${MYSQL_DIR}/xtrabackup-temp | ||
mkdir -p ${TMP_DIR} | ||
xtrabackup --backup --safe-slave-backup --slave-info ${lock_per_table_ddl} --stream=xbstream \ | ||
--host=${DP_DB_HOST} --port=${DP_DB_PORT} \ | ||
--user=${DP_DB_USER} --password=${DP_DB_PASSWORD} \ | ||
--datadir=${DATA_DIR} ${incremental_cmd} \ | ||
2> >(tee ${TMP_DIR}/xtrabackup.log >&2) \ | ||
| datasafed push -z zstd-fastest - "/${DP_BACKUP_NAME}.xbstream.zst" | ||
# record lsn for incremental backups | ||
cat "${TMP_DIR}/xtrabackup.log" \ | ||
| grep "The latest check point (for incremental)" \ | ||
| awk -F"'" '{print $2}' \ | ||
| datasafed push - "/${DP_BACKUP_NAME}.lsn" | ||
TOTAL_SIZE=$(datasafed stat / | grep TotalSize | awk '{print $2}') | ||
echo "{\"totalSize\":\"$TOTAL_SIZE\"}" >"${DP_BACKUP_INFO_FILE}" | ||
rm -rf ${PARENT_DIR} | ||
rm -rf ${TMP_DIR} |
Oops, something went wrong.