feat(mysql): 添加MySQL全量备份与还原脚本及文档
新增备份脚本backup-sync.sh和还原脚本restore-sync.sh,用于处理严重复制冲突场景 更新故障分析文档,补充全量备份还原的操作流程和注意事项 添加测试流程模板文件_TEST_FLOW_TEMPLATE.md 更新SKILL.md文档,增加测试流程分析相关内容
This commit is contained in:
@@ -0,0 +1,132 @@
|
||||
#!/bin/bash
|
||||
|
||||
TAG=""
|
||||
while getopts "t:" opt; do
|
||||
case $opt in
|
||||
t) TAG="$OPTARG" ;;
|
||||
*) echo "Invalid option: -$OPTARG" >&2; exit 1 ;;
|
||||
esac
|
||||
done
|
||||
shift $((OPTIND-1))
|
||||
|
||||
cd /data/backup/mysql || exit 1
|
||||
if [ -n "$TAG" ]; then
|
||||
BACKUP_DIR="./$(date +%Y%m%d%H%M%S)_${TAG}"
|
||||
else
|
||||
BACKUP_DIR="./$(date +%Y%m%d%H%M%S)"
|
||||
fi
|
||||
|
||||
mkdir -p "$BACKUP_DIR"
|
||||
|
||||
MYSQL_USER="root"
|
||||
MYSQL_PASSWORD="ENC(VN13kACOdhyl7xYqbgDMTMP0fK4dwoCkFe0AQW0VEt7/tpwx96GzRVY6eIpwlASM)"
|
||||
MYSQL_HOST="127.0.0.1"
|
||||
|
||||
if [[ "$MYSQL_PASSWORD" =~ ^ENC\(.*\)$ ]]; then
|
||||
encrypted_pwd="${MYSQL_PASSWORD:4:-1}"
|
||||
if ! MYSQL_PASSWORD=$(java -cp /data/secure/jasypt-agent.jar com.jasypt.agent.DecryptionCLI $encrypted_pwd \
|
||||
2>&1); then
|
||||
echo -e "\033[31m[Fatal Error] Password decryption failed. Reason:"
|
||||
echo "$MYSQL_PASSWORD" | grep -iE "error|exception"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
# Function to execute MySQL command
|
||||
mysql_exec() {
|
||||
docker exec -i mysql mysql -u "$MYSQL_USER" -p"$MYSQL_PASSWORD" -h "$MYSQL_HOST" -N -e "$1" 2>/dev/null
|
||||
}
|
||||
|
||||
# Function to restore MySQL state (called on exit)
|
||||
restore_mysql_state() {
|
||||
if [ "$READ_ONLY_SET" = "true" ]; then
|
||||
echo "Restoring MySQL state..."
|
||||
mysql_exec "SET GLOBAL read_only = OFF;" || echo "[Warning] Failed to set read_only = OFF"
|
||||
echo "MySQL state restored"
|
||||
fi
|
||||
}
|
||||
|
||||
# Set trap to ensure MySQL state is restored even on error
|
||||
trap restore_mysql_state EXIT ERR
|
||||
|
||||
# Pre-backup: Set read-only and stop slave
|
||||
echo "Setting MySQL to read-only mode..."
|
||||
if ! mysql_exec "SET GLOBAL read_only = ON;"; then
|
||||
echo "[Critical Error] Failed to set read_only = ON"
|
||||
exit 1
|
||||
fi
|
||||
READ_ONLY_SET="true"
|
||||
|
||||
echo "Stopping slave replication..."
|
||||
if ! mysql_exec "STOP REPLICA;"; then
|
||||
echo "[Warning] Failed to stop replica (may not be a slave server or already stopped)"
|
||||
fi
|
||||
|
||||
# Get GTID position using SELECT @@global.gtid_executed;
|
||||
echo "Getting GTID position..."
|
||||
GTID_EXECUTED=$(mysql_exec "SELECT @@global.gtid_executed;")
|
||||
if [ -n "$GTID_EXECUTED" ]; then
|
||||
# Remove newlines and literal \n strings
|
||||
GTID_EXECUTED=$(echo "$GTID_EXECUTED" | tr -d '\n' | sed 's/\\n//g' | tr -s ' ')
|
||||
echo "GTID Executed: $GTID_EXECUTED"
|
||||
# Write GTID to file for restore use
|
||||
echo "$GTID_EXECUTED" > "$BACKUP_DIR/gtid_executed.txt"
|
||||
else
|
||||
echo "[Warning] Failed to get GTID executed information"
|
||||
fi
|
||||
|
||||
# Get database list for backup
|
||||
if [ $# -eq 0 ]; then
|
||||
# When no arguments, get all non-system databases
|
||||
databases=$(mysql_exec "SHOW DATABASES;" | grep -Ev "(Database|information_schema|performance_schema|mysql|skywalking|sys)")
|
||||
|
||||
# Convert to array and check empty values
|
||||
readarray -t db_list <<< "$databases" || {
|
||||
echo "ERROR: No valid databases found or failed to retrieve database list"
|
||||
restore_mysql_state
|
||||
exit 1
|
||||
}
|
||||
else
|
||||
# Use arguments as database list when provided
|
||||
db_list=("$@")
|
||||
fi
|
||||
|
||||
# Check if database list is empty
|
||||
if [ ${#db_list[@]} -eq 0 ]; then
|
||||
echo "ERROR: No databases to backup"
|
||||
restore_mysql_state
|
||||
exit 1
|
||||
fi
|
||||
|
||||
backup_list_str="$BACKUP_DIR.7z"
|
||||
# Perform backup
|
||||
for db in "${db_list[@]}"; do
|
||||
echo "Backing up database: $db"
|
||||
backup_list_str="$backup_list_str $db"
|
||||
if ! docker exec -i mysql mysqldump -u "$MYSQL_USER" -p"$MYSQL_PASSWORD" -h "$MYSQL_HOST" --set-gtid-purged=OFF --single-transaction --databases "$db" > "$BACKUP_DIR/$db.sql"; then
|
||||
echo "[Critical Error] Failed to backup database $db, aborting"
|
||||
restore_mysql_state
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
|
||||
# Post-backup: Restore MySQL state (before compression)
|
||||
echo "Restoring MySQL to read-write mode..."
|
||||
mysql_exec "SET GLOBAL read_only = OFF;" || echo "[Warning] Failed to set read_only = OFF"
|
||||
|
||||
# Clear the trap since we've successfully restored
|
||||
READ_ONLY_SET="false"
|
||||
trap - EXIT ERR
|
||||
|
||||
# Compress backup files
|
||||
if ! 7zz a "$BACKUP_DIR.7z" "$BACKUP_DIR" >/dev/null; then
|
||||
echo "Compression failed. Please check disk space or 7z installation"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Cleanup temporary files
|
||||
rm -rf "$BACKUP_DIR"
|
||||
echo "Backup completed: $BACKUP_DIR.7z"
|
||||
echo $backup_list_str >> backup_list.txt
|
||||
|
||||
echo "Backup process completed successfully"
|
||||
Reference in New Issue
Block a user