diff options
| author | Michal Arbet <michal.arbet@ultimum.io> | 2025-05-27 09:04:40 +0200 |
|---|---|---|
| committer | Michal Arbet <michal.arbet@ultimum.io> | 2025-05-30 18:07:48 +0200 |
| commit | bcf37e5016ecf1bc50dea111285cad887fd471b3 (patch) | |
| tree | 0cd9ea8b0b0c405972d1e5fe07443ed149403b51 | |
| parent | 32d2f1719a978c62a44ca998b8018692b55ac0d4 (diff) | |
| download | kolla-bcf37e5016ecf1bc50dea111285cad887fd471b3.tar.gz kolla-bcf37e5016ecf1bc50dea111285cad887fd471b3.zip | |
[mariadb] Fix incremental backup using correct base dir
The original script used --incremental-history-name and compressed
full backups as gzip streams. This failed because mariabackup expects
an actual decompressed base directory for incremental backups.
This patch:
- Decompresses the latest full backup into a temporary directory
- Uses that as --incremental-basedir
- Aligns the backup flow with official Mariabackup documentation:
https://mariadb.com/kb/en/incremental-backup-and-restore-with-mariabackup/
This makes the incremental process reliable and fully supported.
Closes-Bug: #2111620
Change-Id: I562ce5e54752015863a20bf113bce74a69e02331
| -rw-r--r-- | docker/mariadb/mariadb-server/backup.sh | 59 | ||||
| -rw-r--r-- | docker/mariadb/mariadb-server/backup_replica.sh | 65 | ||||
| -rw-r--r-- | releasenotes/notes/bug-2111620-e40e1dec6fed309f.yaml | 12 |
3 files changed, 89 insertions, 47 deletions
diff --git a/docker/mariadb/mariadb-server/backup.sh b/docker/mariadb/mariadb-server/backup.sh index 30796fa4e..be63cd938 100644 --- a/docker/mariadb/mariadb-server/backup.sh +++ b/docker/mariadb/mariadb-server/backup.sh @@ -6,49 +6,66 @@ set -o pipefail # Execute a full backup backup_full() { echo "Taking a full backup" - LAST_FULL_DATE=$(date +%d-%m-%Y) + LAST_FULL_DATE=$(date +%d-%m-%Y-%s) + BACKUP_FILE="mysqlbackup-${LAST_FULL_DATE}.qp.xbc.xbs.gz" + BACKUP_PATH="$BACKUP_DIR/full-${LAST_FULL_DATE}" + mkdir -p "$BACKUP_PATH" + mariabackup \ --defaults-file=/etc/mysql/my.cnf \ --backup \ --stream=xbstream \ --history=$LAST_FULL_DATE | gzip > \ - $BACKUP_DIR/mysqlbackup-$(date +%d-%m-%Y-%s).qp.xbc.xbs.gz - echo $LAST_FULL_DATE > $BACKUP_DIR/last_full_date + "$BACKUP_PATH/$BACKUP_FILE" + + echo "$BACKUP_PATH/$BACKUP_FILE" > "$BACKUP_DIR/last_full_file" } # Execute an incremental backup backup_incremental() { echo "Taking an incremental backup" - if [ -r $BACKUP_DIR/last_full_date ]; then - LAST_FULL_DATE=$(cat $BACKUP_DIR/last_full_date) - fi - if [ -z $LAST_FULL_DATE ]; then - LAST_FULL_DATE=$(date +%d-%m-%Y) + + if [ ! -r "$BACKUP_DIR/last_full_file" ]; then + echo "Error: No full backup file found." + exit 1 fi + + FULL_BACKUP_FILE=$(cat "$BACKUP_DIR/last_full_file") + LAST_FULL_DATE=$(basename "$(dirname "$FULL_BACKUP_FILE")" | sed 's/^full-//') + NOW=$(date +%H-%M-%S-%d-%m-%Y) + INCR_DIR="$BACKUP_DIR/incr-${NOW}-since-${LAST_FULL_DATE}" + mkdir -p "$INCR_DIR" + + TMP_BASEDIR=$(mktemp -d) + echo "Decompressing full backup to temp dir: $TMP_BASEDIR" + gunzip -c "$FULL_BACKUP_FILE" | mbstream -x -C "$TMP_BASEDIR" + mariabackup \ --defaults-file=/etc/mysql/my.cnf \ --backup \ --stream=xbstream \ - --incremental-history-name=$LAST_FULL_DATE \ - --history=$LAST_FULL_DATE | gzip > \ - $BACKUP_DIR/incremental-$(date +%H)-mysqlbackup-$(date +%d-%m-%Y-%s).qp.xbc.xbs.gz + --incremental-basedir="$TMP_BASEDIR" \ + --history="incr-${NOW}" | gzip > \ + "$INCR_DIR/incremental-${NOW}-mysqlbackup-${LAST_FULL_DATE}.qp.xbc.xbs.gz" + + rm -rf "$TMP_BASEDIR" } BACKUP_DIR=/backup/ -cd $BACKUP_DIR +cd "$BACKUP_DIR" -if [ -n $BACKUP_TYPE ]; then - case $BACKUP_TYPE in +if [ -n "${BACKUP_TYPE:-}" ]; then + case "$BACKUP_TYPE" in "full") - backup_full - ;; + backup_full + ;; "incremental") - backup_incremental - ;; + backup_incremental + ;; *) - echo "Only full or incremental options are supported." - exit 1 - ;; + echo "Only full or incremental options are supported." + exit 1 + ;; esac else echo "You need to specify either full or incremental backup options." diff --git a/docker/mariadb/mariadb-server/backup_replica.sh b/docker/mariadb/mariadb-server/backup_replica.sh index 7f86a18a7..ebdcbf6b0 100644 --- a/docker/mariadb/mariadb-server/backup_replica.sh +++ b/docker/mariadb/mariadb-server/backup_replica.sh @@ -23,35 +23,48 @@ cd "${BACKUP_DIR}" backup_full() { echo "Taking a full backup" LAST_FULL_DATE=$(date +%d-%m-%Y-%s) + BACKUP_FILE="backup-full-${LAST_FULL_DATE}.mbs.gz" + BACKUP_PATH="${BACKUP_DIR}/full-${LAST_FULL_DATE}" + mkdir -p "${BACKUP_PATH}" + mariabackup \ --defaults-file="${REPLICA_MY_CNF}" \ --backup \ --stream=mbstream \ - --history="${LAST_FULL_DATE}" | gzip > \ - "${BACKUP_DIR}/mysqlbackup-${LAST_FULL_DATE}.qp.mbc.mbs.gz" && \ - echo "${LAST_FULL_DATE}" > "${BACKUP_DIR}/last_full_date" + --history="${LAST_FULL_DATE}" \ + | gzip > "${BACKUP_PATH}/${BACKUP_FILE}" + + echo "${BACKUP_PATH}/${BACKUP_FILE}" > "${BACKUP_DIR}/last_full_file" } # Execute an incremental backup backup_incremental() { - if [ -r "${BACKUP_DIR}/last_full_date" ]; then - LAST_FULL_DATE=$(cat "${BACKUP_DIR}/last_full_date") - else - LAST_FULL_DATE="" - fi - if [ ! -z "${LAST_FULL_DATE}" ]; then - echo "Taking an incremental backup" - mariabackup \ - --defaults-file="${REPLICA_MY_CNF}" \ - --backup \ - --stream=mbstream \ - --incremental-history-name="${LAST_FULL_DATE}" \ - --history="${LAST_FULL_DATE}" | gzip > \ - "${BACKUP_DIR}/incremental-$(date +%H)-mysqlbackup-${LAST_FULL_DATE}.qp.mbc.mbs.gz" - else - echo "Error: Full backup don't exist." + if [ ! -r "${BACKUP_DIR}/last_full_file" ]; then + echo "Error: No full backup file found." exit 1 fi + + FULL_BACKUP_FILE=$(cat "${BACKUP_DIR}/last_full_file") + LAST_FULL_DATE=$(basename "$(dirname "${FULL_BACKUP_FILE}")" | sed 's/^full-//') + NOW=$(date +%H-%M-%S-%d-%m-%Y) + INCR_DIR="${BACKUP_DIR}/incr-${NOW}-since-${LAST_FULL_DATE}" + mkdir -p "${INCR_DIR}" + + # Temp dir for full base restore + TMP_BASEDIR=$(mktemp -d) + + echo "Decompressing full backup to temp dir: ${TMP_BASEDIR}" + gunzip -c "${FULL_BACKUP_FILE}" | mbstream -x -C "${TMP_BASEDIR}" + + mariabackup \ + --defaults-file="${REPLICA_MY_CNF}" \ + --backup \ + --stream=mbstream \ + --incremental-basedir="${TMP_BASEDIR}" \ + --history="incr-${NOW}" \ + | gzip > "${INCR_DIR}/backup-incremental-${NOW}.mbs.gz" + + rm -rf "${TMP_BASEDIR}" } # Retry logic for database queries @@ -119,15 +132,15 @@ if [ -n "${BACKUP_TYPE}" ]; then get_and_set_replica_server case "${BACKUP_TYPE}" in "full") - backup_full - ;; + backup_full + ;; "incremental") - backup_incremental - ;; + backup_incremental + ;; *) - echo "Only full or incremental options are supported." - exit 1 - ;; + echo "Only full or incremental options are supported." + exit 1 + ;; esac else echo "You need to specify either full or incremental backup options." diff --git a/releasenotes/notes/bug-2111620-e40e1dec6fed309f.yaml b/releasenotes/notes/bug-2111620-e40e1dec6fed309f.yaml new file mode 100644 index 000000000..e5c9f8198 --- /dev/null +++ b/releasenotes/notes/bug-2111620-e40e1dec6fed309f.yaml @@ -0,0 +1,12 @@ +--- +fixes: + - | + Fixes incremental MariaDB backups by switching to directory-based base backups, + following official Mariabackup recommendations. + `LP#2111620 <https://bugs.launchpad.net/kolla/+bug/2111620>`__ +upgrade: + - | + Backup files are now stored in timestamped directories and have new filenames. + This does not affect restore, as Kolla Ansible does not support automated restore; + users perform restores manually. A new full backup is recommended after upgrade + to ensure incremental backups work correctly. |
