mysql分别在windows和linux下的备份策略

嗟乎!

一、概述

mysql数据库该怎么备份呢?

数据库备份有几个概念:全量备份、增量备份、差异备份。当然啦,数据库备份又有冷备份和热备份,即物理备份和逻辑备份之分。冷备份就是将mysql停了,然后直接拷贝它的数据文件,简单粗暴。问题是,数据库怎可轻易停止或重启?所以我们通常说的备份都是指热备份,即逻辑备份。逻辑备份包括全量备份、增量备份、差异备份。

全量备份就是整个库备份。增量备份是将上一次全量备份或增量备份后的变化备份。差异备份是将上次全量备份后的变化备份。所以增量备份和差异备份有重叠。由于mysql中,并不直接支持所谓增量备份或差异备份,所谓的加过滤条件简直就是瞎掰,根本不属于自动备份的概念,毫无意义。mysql只能通过拷贝二进制日志文件(BinLog)来实现增量备份的效果,聊胜于无。BinLog里面,记录了对mysql的增删改,而没有记录查,所以重新执行这个BinLog就可以达到增量备份的效果。有关BinLog,可以参考拙作(mysql的日志文件

二、备份思路

将备份命令写到批处理文件,然后定期运行它们。windows的可以用操作系统的任务计划来定期执行批处理;linux可以设置定时器crontab。

另外,备份文件一般比较大,为长久计,备份之后,应将备份文件压缩。

三、windows

1、全量备份

bash 复制代码
@echo off
rem 设置 MySQL 用户名和密码
set MYSQL_USER=数据库账号
set MYSQL_PASSWORD=密码
set DATABASE=待备份的数据库名称
rem mysql数据文件路径。一般在mysql安装路径,可在mysql.ini里设置。
set MYSQL_BIN=e:\mysql\data\
rem 设置备份文件路径
set BACKUP_PATH=C:\temp\backup

rem 获取当前时间戳作为备份文件名
for /f "delims=" %%a in ('powershell -command "Get-Date -Format 'yyyyMMdd_HHmmss'"') do set TIMESTAMP=%%a

set FULL_BACKUP_FILE=%BACKUP_PATH%\full_backup_%TIMESTAMP%.sql
set COMPRESSED_FULL_BACKUP_FILE=%FULL_BACKUP_FILE%.zip

rem 检查是否已存在该时刻的备份文件,如果存在则不备份
if not exist %COMPRESSED_FULL_BACKUP_FILE% (
    rem 执行全量备份
    mysqldump -u%MYSQL_USER% -p%MYSQL_PASSWORD% %DATABASE% --single-transaction --routines --triggers > %FULL_BACKUP_FILE%
    echo Full Backup completed: %FULL_BACKUP_FILE%
    
    rem 压缩备份文件。这里使用360zip
    360zip -ar %FULL_BACKUP_FILE% %COMPRESSED_FULL_BACKUP_FILE% 
    rem 删除备份文件
    del %FULL_BACKUP_FILE%
) else (
    echo Full Backup file already exists: %COMPRESSED_FULL_BACKUP_FILE%
)

2、增量备份

bash 复制代码
rem 设置 MySQL 用户名和密码
set MYSQL_USER=数据库账号
set MYSQL_PASSWORD=密码
set DATABASE=待备份的数据库名称
rem mysql数据文件路径。一般在mysql安装路径,可在mysql.ini里设置。
set MYSQL_BIN=e:\mysql\data\
rem 设置备份文件路径
set BACKUP_PATH=C:\temp\backup

rem 获取当前时间戳作为备份文件名
for /f "delims=" %%a in ('powershell -command "Get-Date -Format 'yyyyMMdd_HHmmss'"') do set TIMESTAMP=%%a

rem 生成的备份文件名称
set BINLOG_FILE=%BACKUP_PATH%\mysql-bin.%TIMESTAMP%
rem 压缩后的备份文件名称
set COMPRESSED_BINLOG_FILE=%BINLOG_FILE%.zip
rem 增量备份对应的position
set BINLOG_POSITION_FILE=%BACKUP_PATH%\binlog_position.txt

rem 检查是否已存在该时刻的二进制日志文件,如果存在则不备份
if not exist %COMPRESSED_BINLOG_FILE% (
    rem 获取当前二进制日志文件名和位置
    for /f "tokens=1,2" %%i in ('mysql -u%MYSQL_USER% -p%MYSQL_PASSWORD% -e "SHOW MASTER STATUS" ^| find " " /v') do (
        set CURRENT_BINLOG_FILE=%%i
        set CURRENT_BINLOG_POSITION=%%j
    )
    rem 拷贝二进制日志文件到备份目录
    copy /Y %MYSQL_BIN%%CURRENT_BINLOG_FILE% %BINLOG_FILE%
    rem 压缩
    360zip -ar %BINLOG_FILE% %COMPRESSED_BINLOG_FILE%
    rem 删除备份文件
    del %BINLOG_FILE%

    rem 将二进制日志信息保存到文件,增量备份恢复时使用
    echo %COMPRESSED_BINLOG_FILE% %BINLOG_POSITION% > %BINLOG_POSITION_FILE%       
) else (
    echo Compressed Binary log file already exists: %COMPRESSED_BINLOG_FILE%
)

四、linux

1、全量备份

bash 复制代码
#!/bin/bash

# 设置 MySQL 用户名和密码
MYSQL_USER=数据库账号
MYSQL_PASSWORD=密码
DATABASE=待备份的数据库名称
MYSQL_PORT=mysql端口
MYSQL_HOST=mysqlIP地址

# 设置备份文件路径
BACKUP_PATH="/home/admin/db-backup/files"

# 获取当前时间戳作为备份文件名
TIMESTAMP=$(date +"%Y%m%d_%H%M%S")

# 备份文件名
FULL_BACKUP_FILE="$BACKUP_PATH/full_backup_$TIMESTAMP.sql"

# 检查是否已存在备份文件,如果存在则不再创建
if [ ! -f "$FULL_BACKUP_FILE" ]; then
    # 执行全量备份
    mysqldump -h"$MYSQL_HOST" -P"$MYSQL_PORT" -u"$MYSQL_USER" -p"$MYSQL_PASSWORD" "$DATABASE" --single-transaction --routines --triggers > "$FULL_BACKUP_FILE"
    # 压缩全量备份文件
    gzip "$FULL_BACKUP_FILE"
    echo "Full Backup completed: $FULL_BACKUP_FILE"
else
    echo "Full Backup file already exists: $FULL_BACKUP_FILE"
fi

2、增量备份

获取当前二进制日志文件名和位置的时候,要使用mysql命令。由于该命令在bash文件中执行,可能系统会找不到mysql,提示未知命令,所以要指定mysql路径。如果不清楚mysql安装在什么地方,可以敲入:

bash 复制代码
which mysql

这样可以得到mysql所在路径,如:/usr/local/mysql/mysql-8.0/bin/mysql,

然后据此修改bash文件。

bash 复制代码
#!/bin/bash

# 设置 MySQL 用户名和密码
MYSQL_USER=数据库账号
MYSQL_PASSWORD=密码
DATABASE=待备份的数据库名称
MYSQL_PORT=mysql端口
MYSQL_HOST=mysqlIP地址

# MySQL 数据文件路径
MYSQL_BIN="/home/admin/mysql/data/"
# 设置备份文件路径
BACKUP_PATH="/home/admin/db-backup/files"
# 获取当前时间戳作为备份文件名
TIMESTAMP=$(date +"%Y%m%d_%H%M%S")

BINLOG_FILE="$BACKUP_PATH/mysql-bin.$TIMESTAMP"
COMPRESSED_BINLOG_FILE="$BINLOG_FILE.gz"
BINLOG_POSITION_FILE="$BACKUP_PATH/binlog_position.txt"

# 检查是否已存在二进制日志文件,如果存在则不再创建
if [ ! -f "$COMPRESSED_BINLOG_FILE" ]; then
    # 获取当前二进制日志文件名和位置
    read -r CURRENT_BINLOG_FILE CURRENT_BINLOG_POSITION <<<$(/usr/local/mysql/mysql-8.0/bin/mysql -h"$MYSQL_HOST" -P"$MYSQL_PORT" -u"$MYSQL_USER" -p"$MYSQL_PASSWORD" -e "SHOW MASTER STATUS" | awk 'NR==2{print $1, $2}')
    
    # 拷贝并压缩二进制日志文件到备份目录
    cp "$MYSQL_BIN$CURRENT_BINLOG_FILE" "$BINLOG_FILE"
    gzip "$BINLOG_FILE"

    # 将二进制日志信息保存到文件,以备增量备份时使用
    echo "$COMPRESSED_BINLOG_FILE $BINLOG_POSITION" > "$BINLOG_POSITION_FILE"
else
    echo "Compressed Binary log file already exists: $COMPRESSED_BINLOG_FILE"
fi

3、定时执行

1)首先将shell文件赋权为可执行文件。这一步好像不是必要的。

bash 复制代码
chmod 777 backup.sh

2)切换为超级管理员

bash 复制代码
su

3)设置定时器

输入命令

bash 复制代码
crontab -e

在打开的界面中输入

bash 复制代码
0 3 * * 6 sh /home/admin/db-backup/backup.sh

意思是每周六凌晨3点执行。

五、小结

mysql并不天然支持增量备份,这是我没想到的。之前sql server不论是全量、差异备份,都有直接的命令,可以交替执行。mysql吹得天上有,地上无,感觉有些基本的配套功能都没有。另外,mysql应该是国内最流行的数据库了,按说相关教程、方案都非常完备了,稍微搜一下,资料就会一大把,但事实上好像并非如此。尤其这个差异备份、增量备份,我还真没看到多少。这里面,原因可能是多方面的,一是mysql多用于互联网,互联网的特点就是迭代快,赶工厉害,很少有时间停下来总结一下。二是国内互联网日益封闭,质量越来越差,搜索引擎都没什么好搜的,也搜不到什么有价值的东西。如果不是chatGPT的指导,还真不容易写出上面的批处理。

相关文章
mysql备份及还原
linux下设置定期执行需要root权限的sh文件

相关推荐
Python之栈42 分钟前
【无标题】
数据库·python·mysql
亦世凡华、1 小时前
MySQL--》如何在MySQL中打造高效优化索引
数据库·经验分享·mysql·索引·性能分析
White_Mountain11 小时前
在Ubuntu中配置mysql,并允许外部访问数据库
数据库·mysql·ubuntu
老王笔记11 小时前
GTID下复制问题和解决
mysql
Lojarro13 小时前
【Spring】Spring框架之-AOP
java·mysql·spring
TianyaOAO13 小时前
mysql的事务控制和数据库的备份和恢复
数据库·mysql
Ewen Seong13 小时前
mysql系列5—Innodb的缓存
数据库·mysql·缓存
W215515 小时前
Liunx下MySQL:表的约束
数据库·mysql
nbsaas-boot16 小时前
探索 JSON 数据在关系型数据库中的应用:MySQL 与 SQL Server 的对比
数据库·mysql·json
奥顺16 小时前
PHPUnit使用指南:编写高效的单元测试
大数据·mysql·开源·php