前言

提示:在docker环境脚本一键按照mysql8.0数据库,方便快捷省事省时,包括如何定时备份和恢复 我的安装目录是/software/mysql下,如果需要修改自行修改脚本,我的默认密码是123456
![![![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/adf44b02591c4a8ab33529673f60911e.png](https://i-blog.csdnimg.cn/direct/23d312a3b5054206b96d1252793b83a8.png](https://i-blog.csdnimg.cn/direct/a1cf819ef3034ed3be5aad1beff05e19.png


一、安装MySql8.0版本

1.1 安装脚本 (install_mysql.sh)

提示:创建my-network,否则删除 --network my-network \

新建文件 install_mysql.sh*,内容如下:

#!/bin/bash

# 设置变量
MYSQL_ROOT_PASSWORD="123456"
MYSQL_VERSION="8.0.26"
MYSQL_PORT="3306"
MYSQL_BASE_DIR="/software/mysql"
TEMP_CONTAINER_NAME="mysql_temp_$(date +%s)"  # 使用时间戳避免冲突

echo "开始安装MySQL..."

# 检查端口是否被占用
if netstat -tuln | grep ":${MYSQL_PORT} " > /dev/null; then
    echo "错误:端口 ${MYSQL_PORT} 已被占用!"
    exit 1
fi

# 清理可能存在的旧临时容器
docker rm -f mysql_temp 2>/dev/null || true
docker rm -f ${TEMP_CONTAINER_NAME} 2>/dev/null || true

# 创建必要的目录(如果不存在)
sudo mkdir -p ${MYSQL_BASE_DIR}/data
sudo mkdir -p ${MYSQL_BASE_DIR}/config
sudo mkdir -p ${MYSQL_BASE_DIR}/logs

# 只有第一次才复制默认配置
if [ ! -f "${MYSQL_BASE_DIR}/config/my.cnf" ]; then
    echo "正在启动临时MySQL容器以获取默认配置..."
    
    # 运行临时容器
    docker run \
        -d \
        -p ${MYSQL_PORT}:3306 \
        --name ${TEMP_CONTAINER_NAME} \
        -e MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD} \
        mysql:${MYSQL_VERSION}

    # 等待MySQL启动完成
    echo "等待MySQL启动..."
    
    # 更好的等待方式
    for i in {1..60}; do
        if docker exec ${TEMP_CONTAINER_NAME} mysqladmin ping -h localhost --silent; then
            echo "MySQL已启动"
            break
        fi
        echo "等待MySQL启动... ($i/60)"
        sleep 2
    done

    # 复制配置文件
    echo "复制配置文件..."
    docker cp ${TEMP_CONTAINER_NAME}:/etc/mysql/. ${MYSQL_BASE_DIR}/config

    # 停止并删除临时容器
    echo "清理临时容器..."
    docker stop ${TEMP_CONTAINER_NAME}
    docker rm ${TEMP_CONTAINER_NAME}

    # 修改配置文件,忽略表名大小写
    if ! grep -q "lower_case_table_names" ${MYSQL_BASE_DIR}/config/my.cnf; then
        echo "lower_case_table_names=1" | sudo tee -a ${MYSQL_BASE_DIR}/config/my.cnf
    fi
else
    echo "配置文件已存在,跳过配置生成步骤..."
fi

# 设置正确的目录权限(仅在需要时)
if [ -d "${MYSQL_BASE_DIR}/data" ]; then
    sudo chown -R 999:999 ${MYSQL_BASE_DIR}/data 2>/dev/null || true
fi
if [ -d "${MYSQL_BASE_DIR}/logs" ]; then
    sudo chown -R 999:999 ${MYSQL_BASE_DIR}/logs 2>/dev/null || true
fi

echo "MySQL安装完成!"
echo "数据目录: ${MYSQL_BASE_DIR}/data"
echo "配置目录: ${MYSQL_BASE_DIR}/config"
echo "日志目录: ${MYSQL_BASE_DIR}/logs"

1.2 启动脚本 (start_mysql.sh)

#!/bin/bash

# 设置变量
MYSQL_ROOT_PASSWORD="123456"
MYSQL_VERSION="8.0.26"
MYSQL_PORT="3306"
MYSQL_BASE_DIR="/software/mysql"

echo "正在启动MySQL容器..."

# 检查端口是否被占用
if netstat -tuln | grep ":${MYSQL_PORT} " > /dev/null; then
    echo "错误:端口 ${MYSQL_PORT} 已被占用!"
    exit 1
fi

# 检查网络是否存在
if ! docker network ls | grep -q my-network; then
    echo "警告:网络 'my-network' 不存在,创建中..."
    docker network create my-network
fi

# 检查是否已存在同名容器
CONTAINER_EXISTS=$(docker ps -a --filter "name=mysql" --format "{{.Names}}")
if [ ! -z "$CONTAINER_EXISTS" ]; then
    echo "发现已存在的MySQL容器,正在停止并删除..."
    docker stop mysql >/dev/null 2>&1
    docker rm mysql >/dev/null 2>&1
    echo "旧容器已清理"
fi

# 检查数据目录是否存在且非空
if [ -d "${MYSQL_BASE_DIR}/data" ] && [ "$(ls -A ${MYSQL_BASE_DIR}/data)" ]; then
    echo "警告:数据目录非空,将使用现有数据启动"
    echo "      如果MySQL版本不同,可能导致启动失败"
fi

# 检查配置文件
if [ ! -f "${MYSQL_BASE_DIR}/config/my.cnf" ]; then
    echo "警告:配置文件不存在,将使用默认配置"
    mkdir -p ${MYSQL_BASE_DIR}/config
fi

# 设置正确的权限(可选)
if [ -d "${MYSQL_BASE_DIR}/data" ]; then
    sudo chown -R 999:999 ${MYSQL_BASE_DIR}/data 2>/dev/null || true
fi

# 启动最终的MySQL容器
echo "启动MySQL容器..."
docker run \
-d \
-p ${MYSQL_PORT}:3306 \
--name mysql \
--restart unless-stopped \
--privileged \
--network my-network \
--log-opt max-size=50m \
--log-opt max-file=3 \
-v /etc/localtime:/etc/localtime:ro \
-v ${MYSQL_BASE_DIR}/data:/var/lib/mysql \
-v ${MYSQL_BASE_DIR}/config:/etc/mysql \
-v ${MYSQL_BASE_DIR}/logs:/var/log/mysql \
-e MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD} \
-e TZ=Asia/Shanghai \
mysql:${MYSQL_VERSION}

if [ $? -ne 0 ]; then
    echo "✗ 容器启动失败!"
    exit 1
fi

# 等待容器启动(更智能的等待)
echo "等待MySQL服务启动..."
for i in {1..30}; do
    if docker exec mysql mysqladmin ping -h localhost --silent 2>/dev/null; then
        echo "✓ MySQL服务已就绪"
        break
    fi
    echo "等待中... ($i/30)"
    sleep 2
done

# 检查容器状态
echo "检查MySQL容器状态..."
if docker ps | grep -q mysql; then
    echo "✓ MySQL容器运行正常"
    
    # 验证数据库连接
    if docker exec mysql mysql -uroot -p${MYSQL_ROOT_PASSWORD} -e "SELECT 1" 2>/dev/null; then
        echo "✓ MySQL数据库连接成功"
    else
        echo "⚠ 容器运行但数据库连接失败"
    fi
else
    echo "✗ MySQL容器未运行!"
    echo "查看容器日志:docker logs mysql"
    exit 1
fi

echo ""
echo "MySQL启动完成!"
echo "连接信息:"
echo "端口: ${MYSQL_PORT}"
echo "用户名: root"
echo "密码: ${MYSQL_ROOT_PASSWORD}"
echo "数据目录: ${MYSQL_BASE_DIR}/data"
echo "配置目录: ${MYSQL_BASE_DIR}/config"
echo ""
echo "常用命令:"
echo "查看日志: docker logs mysql"
echo "进入容器: docker exec -it mysql bash"
echo "停止服务: docker stop mysql"

1.3 停止脚本 (stop_mysql.sh)

#!/bin/bash

echo "正在停止MySQL容器..."

if docker ps | grep -q mysql; then
    docker stop mysql
    echo "MySQL容器已停止"
else
    echo "MySQL容器未在运行"
fi

1.4 重启脚本 (restart_mysql.sh)

#!/bin/bash

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"

echo "正在重启MySQL容器..."

# 停止MySQL
if docker ps | grep -q mysql; then
    docker stop mysql
    echo "MySQL容器已停止"
fi

# 启动MySQL
bash ${SCRIPT_DIR}/start_mysql.sh

1.5 添加权限

chmod +x install_mysql.sh start_mysql.sh stop_mysql.sh restart_mysql.sh

二、备份

提示:检查脚本密码和原来数据库密码是否一致,如果不一致设置脚本内的密码,否则恢复后会重置密码!

1.进行数据备份

在backup文件夹下新建mysql_backup.sh 文件,内容如下

#!/bin/bash

# 备份配置
MYSQL_HOST="127.0.0.1"
MYSQL_PORT="3306"
MYSQL_USER="root"
MYSQL_PASSWORD="123456"
BACKUP_BASE_DIR="/software/mysql/backup"
BACKUP_DIR="${BACKUP_BASE_DIR}/backups"
RESTORE_DIR="${BACKUP_BASE_DIR}/restores"
LOG_FILE="${BACKUP_BASE_DIR}/backup.log"
RETENTION_DAYS=7
DATE=$(date +%Y%m%d_%H%M%S)
BACKUP_NAME="mysql_backup_${DATE}"

# 创建备份目录
mkdir -p ${BACKUP_DIR}

# 日志函数
log() {
    echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" >> ${LOG_FILE}
    echo "$1"
}

log "=== 开始MySQL备份 ==="

# 检查MySQL连接
if ! docker exec mysql mysql -h${MYSQL_HOST} -P${MYSQL_PORT} -u${MYSQL_USER} -p${MYSQL_PASSWORD} -e "SELECT 1;" &>/dev/null; then
    log "错误: 无法连接到MySQL"
    exit 1
fi

# 创建临时备份目录
TEMP_DIR="${BACKUP_DIR}/${BACKUP_NAME}"
mkdir -p ${TEMP_DIR}

# 1. 全量数据库备份(重定向错误输出,避免警告混入)
log "执行全量数据库备份..."
docker exec mysql bash -c "mysqldump -h${MYSQL_HOST} -P${MYSQL_PORT} -u${MYSQL_USER} -p${MYSQL_PASSWORD} \
  --all-databases \
  --single-transaction \
  --routines \
  --events \
  --triggers \
  --no-tablespaces \
  2>/dev/null" > ${TEMP_DIR}/databases.sql

if [ $? -eq 0 ] && [ -s ${TEMP_DIR}/databases.sql ]; then
    log "全量备份完成,文件大小: $(du -h ${TEMP_DIR}/databases.sql | cut -f1)"
else
    log "错误: 全量备份失败或文件为空"
    exit 1
fi

# 2. 备份二进制日志位置(可选)
log "备份二进制日志信息..."
docker exec mysql mysql -h${MYSQL_HOST} -P${MYSQL_PORT} -u${MYSQL_USER} -p${MYSQL_PASSWORD} -e "SHOW MASTER STATUS\G" > ${TEMP_DIR}/binlog_info.txt 2>/dev/null

# 3. 创建备份信息文件
cat > ${TEMP_DIR}/backup_info.txt << INFO
备份时间: $(date)
备份名称: ${BACKUP_NAME}
MySQL版本: $(docker exec mysql mysql -h${MYSQL_HOST} -P${MYSQL_PORT} -u${MYSQL_USER} -p${MYSQL_PASSWORD} -s -N -e "SELECT VERSION();" 2>/dev/null)
数据库列表: $(docker exec mysql mysql -h${MYSQL_HOST} -P${MYSQL_PORT} -u${MYSQL_USER} -p${MYSQL_PASSWORD} -s -N -e "SHOW DATABASES;" 2>/dev/null | tr '\n' ' ')
INFO

# 4. 压缩备份文件
log "压缩备份文件..."
cd ${BACKUP_DIR}
tar -czf ${BACKUP_NAME}.tar.gz ${BACKUP_NAME}
rm -rf ${TEMP_DIR}

# 5. 清理旧备份(保留7天)
log "清理过期备份..."
find ${BACKUP_DIR} -name "mysql_backup_*.tar.gz" -mtime +${RETENTION_DAYS} -delete
find ${BACKUP_BASE_DIR} -name "*.log" -mtime +${RETENTION_DAYS} -delete

# 6. 记录备份结果
BACKUP_SIZE=$(du -h ${BACKUP_DIR}/${BACKUP_NAME}.tar.gz | cut -f1)
log "备份完成: ${BACKUP_NAME}.tar.gz (${BACKUP_SIZE})"
log "=== 备份结束 ===\n"

2.修改文件权限

修改文件权限,命令如下:

chmod +x /software/mysql/backup/mysql_backup.sh*

3. 设置定时任务

#1. 编辑root的crontab
sudo crontab -e

# 2.添加以下内容(每天凌晨2点备份):
	0 2 * * * /software/mysql/backup/mysql_backup.sh >> /software/mysql/backup/backup.log 2>&1
# 3.ctrl+o 保存
# 4.Enter 回车确认
# 5.ctrl+X 退出

三、恢复数

提示:检查脚本密码和原来数据库密码是否一致,如果不一致设置脚本内的密码,否则恢复后会重置密码!

1.恢复数据备份脚本

在backup文件夹下新建safe_restore.sh* 文件,内容如下:

#!/bin/bash

echo "=== 安全恢复脚本(修复版) ==="

if [ $# -eq 0 ]; then
    echo "请指定备份文件:"
    ls -lt /software/mysql/backup/backups/*.tar.gz | head -10
    exit 1
fi

BACKUP_FILE=$1
RESTORE_DIR="/tmp/restore_$(date +%s)"

echo "使用备份文件: $BACKUP_FILE"
echo "临时目录: $RESTORE_DIR"

# 解压备份文件
mkdir -p $RESTORE_DIR
tar -xzf "$BACKUP_FILE" -C $RESTORE_DIR

# 查找SQL文件
SQL_FILE=$(find $RESTORE_DIR -name "databases.sql" | head -1)

if [ -z "$SQL_FILE" ]; then
    echo "错误: 未找到databases.sql文件"
    exit 1
fi

echo "找到SQL文件: $SQL_FILE ($(ls -lh $SQL_FILE | awk '{print $5}'))"

# 清理备份文件中的警告信息
echo "清理备份文件中的警告信息..."
CLEANED_SQL="/tmp/cleaned_backup_$(date +%s).sql"
grep -v "WARNING:" "$SQL_FILE" | grep -v "Using a password" > "$CLEANED_SQL"

echo "清理后文件大小: $(ls -lh $CLEANED_SQL | awk '{print $5}')"

# 备份当前数据
echo "创建恢复前备份..."
CURRENT_BACKUP="/software/mysql/backup/restores/restore_$(date +%Y%m%d_%H%M%S).sql"
docker exec mysql mysqldump -uroot -p123456 --all-databases --single-transaction --no-tablespaces > "$CURRENT_BACKUP" 2>/dev/null
echo "当前数据备份: $CURRENT_BACKUP"

# 执行恢复
echo "开始恢复数据..."
if docker exec -i mysql mysql -uroot -p123456 < "$CLEANED_SQL"; then
    echo "✅ 数据恢复成功"
else
    echo "❌ 数据恢复失败"
    echo "尝试从当前备份恢复..."
    docker exec -i mysql mysql -uroot -p123456 < "$CURRENT_BACKUP"
    echo "已恢复原始数据"
    # 清理临时文件
    rm -f "$CLEANED_SQL"
    rm -rf "$RESTORE_DIR"
    exit 1
fi

# 验证恢复
echo "验证恢复..."
docker exec mysql mysql -uroot -p123456 -e "
SHOW DATABASES;
SELECT '恢复完成,密码未改变' as status;
"

# 清理临时文件
rm -f "$CLEANED_SQL"
rm -rf "$RESTORE_DIR"
echo "=== 恢复完成 ==="

2.修改文件权限

修改文件权限,命令如下:

chmod +x /software/mysql/backup/safe_restore.sh* 

3.使用恢复文件脚本

1、cd  /software/mysql/backup
2、./safe_restore.sh +文件名
例如相对路径的恢复文件:./safe_restore.sh  ./mysql_backup_20241202_020001.tar.gz

总结

如果安装完成数据库,进行验证数据库备份恢复,不慎设置密码与原来不一样或者恢复后不知道密码多少时,最简单暴力的方法就是将/software/mysql文件夹下除了安装脚本install_mysql.sh*,其他全部删除,再次进行安装

更多推荐