aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichal Arbet <michal.arbet@ultimum.io>2025-05-27 09:04:40 +0200
committerMichal Arbet <michal.arbet@ultimum.io>2025-05-30 18:07:48 +0200
commitbcf37e5016ecf1bc50dea111285cad887fd471b3 (patch)
tree0cd9ea8b0b0c405972d1e5fe07443ed149403b51
parent32d2f1719a978c62a44ca998b8018692b55ac0d4 (diff)
downloadkolla-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.sh59
-rw-r--r--docker/mariadb/mariadb-server/backup_replica.sh65
-rw-r--r--releasenotes/notes/bug-2111620-e40e1dec6fed309f.yaml12
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.