MySQL数据库备份与恢复
系列文章目录
MySQL的基础操作-CSDN博客
MySQL操作进阶-CSDN博客
MySQL索引事务-CSDN博客
MySQL的JDBC编程-CSDN博客
MySQL存储过程和触发器_mysql 存储过程-CSDN博客
数据库设计简述-CSDN博客
目录
系列文章目录
文章目录
前言
一、MySQL 日志
二、二进制日志
1. 介绍
2. 作用
3. 配置
4. 磁盘文件
5. 日志格式
6. 刷盘策略
7. mysqlbinlog 工具
8. 远程备份 binlog 日志
三、备份
1. 分类
2. 备份方法一:Mysqldump 工具
3. Mysqldump 备份完整过程
1. 备份之前,需收集信息,确保备份内容完整:
2. 创建备份用户及授权:
3. 创建备份目录
4. 生产环境单库备份
5. 完整实例备份
6. 单表多表备份
7. 按条件备份
8. 导出表结构
9. 只备份数据
10. 数据导入
11. 监控恢复进度
4. 备份方法二:SQL 语句导出导入
1. 查看允许导出的目录:
2. sql 语句导入导出
3. mysqlimport 导入
5. 备份方法三:物理备份工具-Xtrabackup
1. 软件安装
2. 全量备份
3. 增量备份
前言
本文系统介绍了MySQL日志系统与备份策略。主要内容包括:1) MySQL各类日志(二进制日志、错误日志等)的功能与配置;2) 二进制日志的格式、刷盘策略及恢复方法;3) 三种备份方法:mysqldump逻辑备份、SQL语句导出导入、XtraBackup物理备份;4) 详细说明全量/增量备份操作流程及恢复步骤。重点阐述了生产环境下的最佳实践,如推荐使用ROW格式二进制日志、sync_binlog=1刷盘策略等。文章为数据库管理员提供了全面的日志管理与备份恢复方案。
一、MySQL 日志
MySQL Server 有一下几种日志:
重做日志(Redo log):用于事务的提交和崩溃时恢复数据;事务中的数据落盘时,如果系统发生奔溃,会记录再重做日志中,服务器重启时,会检查重做日志,重新完成落盘;
回滚日志(Undo log):用于事务回滚;
错误日志(Error log):mysqld 在启动,运行或停止时遇到的问题,都会记录在错误日志中;
一般查询日志(General query log):已建立的客户端连接和冲客户收到的语句;
慢查询日志(slow query log):执行时间超过 long_query_time 指定秒数的查询;
二进制日志(Binary log):更改数据的语句(也用于主从复制);
中继日志(Relay log):从源服务器收到的数据更改;
二、二进制日志
1. 介绍
二进制日志是 mysql 中最重要的日志,日志以事件的形式记录了所有 DDL 和 DML 语句对数据的更改;
DDL:代表数据定义语言1,主要用于定义、修改或删除数据库的结构对象,如创建表、修改列或删除数据库3。典型命令包括 create,alter 和 drop;
DML:代表数据操作语言12,专门负责数据的增删改查操作,如插入记录、更新值或删除行3。常用命令有 insert,update,delete 和 select;
二进制日志还包括每个语句更新时花费的时间信息,启动二进制,对服务器性能稍微有些影响;
二进制日志不会记录 show 和 select 操作;
2. 作用
主从节点数据复制:从节点服务器读取主节点服务器上的二进制日志文件,并根据二进制日志中记录的事件在从节点上执行相同的操作,保证主从节点服务器上的数据一致,实现数据的复制功能;
数据恢复:重新执行记录在二进制日志中的事件,可以完成任一事务之前的数据恢复;
3. 配置
查看 binlog 相关的系统变量:
-- 查看包含 log_bin 的系统配置
show variables like '%log_bin%';
log_bin:是否开启二进制日志;
log_bin_basename:二进制日志的基本文件名;
log_bin_index:二进制日志的索引文件名;
sql_log_bin:会话级别是否开启二进制日志;
在 linux 系统中,bin_log 相关的配置保存在 /etc/mysql/my.cnf 中:
# mysql 的系统配置
[mysqld]
# 配置 mysql 自定义的二进制日志的基本文件名,可以是绝对路径(生产环境),也可以是相对路径(数据目录下)
log_bin = /var/lib/mysql/binlog# 禁用二进制日志
skip-log-bin
# 或者
disable-log-bin# 指定⼆进制⽇志的过期时间
binlog_expire_logs_seconds = 2592000# 指定⼆进制⽇志格式为 ROW
binlog_format = ROW# 二进制日志刷盘策略
sync_binlog = 1# 修改 mysql 为允许远程连接
bind-address = 0.0.0.0
4. 磁盘文件
二进制日志文件名是由基本名+数字扩展名组成的,服务器每次创建一个新的日志文件时,数字扩展名都会增加,从而保证有序的文件序列;
发生以下事件时,服务器都会再创建一个新的日志文件:
- 服务器已启动或者重新启动;
- 服务器刷新日志;
- 当前日志文件的大小达到 max_binlog_size (单个日志文件的最大字节数,最小值 4096 字节,最大值和默认值 1 GB);
二进制日志记录事务,会完整的记录事务;
如果事务比较大,二进制日志也会完整记录,即使超过日志大小限制(1 GB),也会保证事务的完整性;
删除二进制日志文件:
-- 删除指定日志文件之前的所有日志文件并更新索引
PURGE BINARY LOGS TO 'binlog.000010';-- 删除指定时间之前的所有⽇志⽂件并更新索引
PURGE BINARY LOGS BEFORE '2024-10-02 22:56:26';-- 重置⼆进⾏⽇志⽂件和索引⽂件为初始状态
reset master;
5. 日志格式
statement:基于 sql 语句记录日志;
row:基于表中受影响的行记录日志;
mixed:基于语句格式与行格式的混合模式记录日志;
生产环境中使用 row 格式,原因是一些函数比如 now(),uuid() 等函数产生的数据无法使用 statement 格式进行恢复;
6. 刷盘策略
二进制日志的刷盘策略可以通过 sync_binlog 系统变量设置:
sync_binlog = 0:mysql 不控制 binlog 的刷新,由系统控制刷新时机,性能最好,但是风险最大,如果系统发生奔溃,未来得及落盘的二进制日志就会丢失;
sync_binlog = 1:每次提交事务,mysql 刷新 binlog 完成落盘,最安全但性能损耗最高;实际的生产环境推荐使用这种策略;
sync_binlog = N:每提交 N 个事务刷新一次 binlog;
7. mysqlbinlog 工具
常用选项:
--base64-output:把 binlog 中的事件用 base-64 进行编码;
--database:之查看指定数据库的日志;
--no-defaults:不读取选项文件;由于 mysqld 中指定的字符编码集是 utf8mb4 格式,binlog 是二进制格式,因此需要使用这个选项,跳过选项文件的配置;
--offset, -o:跳过日志中的前 N 条记录;
--server-id:显示指定服务器 ID 创建的事件;
--start-datetime:从等于或者晚于 datatime 的第一个事件开始读取日志;
--stop-datatime:从等于或者晚于 datatime 的第一个事件结束;
--start-position:开始读取日志的位置;
--stop-position:停止解码的位置;
语法:
# 查看日志
mysqlbinlog --no-defaults --database=testdb --base64-output=decode-rows -v binlog.000001 | less
mysqlbinlog --no-defaults --database=testdb --base64-output=decode-rows --start-position=1234 --stop-position=5678 -v binlog.000001 | less
通过二进制日志恢复数据:
# 数据库恢复
# 方法一:找到恢复的起始位置,直接通过二进制日志进行恢复
mysqlbinlog --no-defaults --skip-gtids=true --start-position=721 --stop-position=5426 binlog.000001 | mysql -uroot -p -h127.0.0.1 -P3306# 方法二:导出二进制日志到 sql 文件
mysqlbinlog --no-defaults --skip-gtids=true --start-position=721 --stop-position=5426 binlog.000001 > testdb.sql
# 在 mysql 客户端导入 .sql 文件
source /var/lib/mysql/testdb.sql
8. 远程备份 binlog 日志
在主服务器上创建账号:
-- 远程备份 binlog 日志
-- 创建一个用于复制日志的用户
create user 'binloggrep'@'%' identified with mysql_native_password by '123456';
-- 为用户赋予复制权限
grant replication slave on *.* to 'binloggrep'@'%';
-- 刷新权限
flush privileges;
-- 测试登录
mysql -ubinloggrep -p123456
从服务器运行备份:
# 从服务器运行备份
mysqlbinlog --read-from-remote-server --raw --host=49.233.162.74 --port=3306 --user=binloggrep --password=123456 --stop-never binlog.000001 --result-file=D:/BitCourse/code/mysql/logs/bak-
三、备份
1. 分类
逻辑备份:备份数据库的逻辑结构和数据,通常是导出数据库中的数据和对象来实现的,生成的是数据库可以识别的格式,如 sql 语句;
物理备份:直接复制数据库文件,包括数据文件和日志文件等;
冷备份:数据库完全关闭的情况下进行的备份;
热备份:在数据库运行正常的情况下备份,备份过程中数据库服务仍然可用;
温备份:数据库在运行过程中处于只读模式,可以查询数据,不能修改数据;
全量备份:备份数据库或文件系统的所有数据;
增量备份:备份自上次备份发生变化的数据;
差异备份:备份自上次全量备份以来所有变化的数据;
2. 备份方法一:Mysqldump 工具
mysqldump 客户端程序可以执行逻辑备份并生成一组 sql 语句;
应用场景:
- 数据库版本升级;
- 备份表结构或者小于 10GB 以下的数据库;
- 跨数据库类型迁移;
- 云平台之间的迁移;
常用选项:
--all-databases, -A:转储所有数据库中的所有表;
--databases, -B:转储指定数据库(可以写多个数据库),并转储所有表;
--events, -E:转出数据库中的事件;
--flush-logs, -F:在开始转储前刷新日志;
--no-data, -d:不转储表内容;
--routines:转储数据库的存储过程和函数;
--tables:转储指定表(可以多个表);
--trigger:转储每个表中的触发器;
# 导出本地数据库中所有数据到磁盘
mysqldump -uroot -p -h127.0.0.1 -P3306 -B testdb > /backup/mysql/dump.sql# 在命令行通过 mysql 客户工具直接恢复
mysql -uroot -p < /backup/mysql/dump.sql# 也可以在数据库中恢复
source /backup/mysql/dump.sql
存在的问题:
在备份之前会对是所有表进行加锁,意味着在备份之前,正常产生的相关插入,删除,truncate 操作都处于锁等待状态,会对业务造成严重影响,不建议在生产环境中使用;
同时在备份过程中会产生数据不一致的问题:
- 数据已经发生改变,但是这些改变尚未提交,因此备份中可能包含未提交事务中的数据更改;
- 如果在备份期间发生了事务回滚,备份中可能已经包含了已经删除或者修改了的数据;
- 如果在备份期间有新的数据插入,那么这些数据可能不会被备份;
解决方法:
解决备份过程是数据不一致的方法是使用 --single-transaction 选项,确保在备份在事务内运行,保证备份期间的数据一致性;
事务的级别设置为可重复度,确定备份内的事务任何时候读取的数据都相同;
3. Mysqldump 备份完整过程
1. 备份之前,需收集信息,确保备份内容完整:
-- 查看数据库的表信息
selecttable_schema,table_name,table_collation,ENGINE,table_rows
FROMinformation_schema.TABLES
WHEREtable_schema NOT IN ( 'information_schema', 'sys', 'mysql', 'performance_schema' );-- 查看是否存在存储过程
select count(*) from information_schema.routines;-- 查看是否存在触发器
select count(*) from information_schema.triggers;-- 查看是否存在调度事件
select count(*) from information_schema.events;-- 查看字符集
show variables like 'character%';-- 查看数据库连接超时时间
show variables like 'wait_timeout%';-- 查看交互式连接超时时间
show variables like 'interactive_timeout';-- 查看数据包⼤⼩限制,,建议128M或256M,防⽌包过⼤⽽失败,默认64MB,最⼤1GB
show variables like 'max_allowed_packet'; -- 查看事务是否⾃动提交
show variables like 'autocommit';
2. 创建备份用户及授权:
-- mysql 8.0
-- 创建备份用户
create user 'backup_user'@'localhost' identified with mysql_native_password by '123456';
-- 授权
grant BACKUP_ADMIN,PROCESS,SELECT,RELOAD, LOCK TABLES, REPLICATION CLIENT, EVENT on *.* to 'backup_user'@'localhost';-- mysql 5.7
-- 创建备份用户
CREATE USER 'backup_user'@'localhost' IDENTIFIED BY '123456';
-- 授权
grant reload,lock tables,replication client,create tablespace,process,super,select,event,trigger,show view on *.* to 'backup_user'@'localhost';
3. 创建备份目录
mkdir -p /backup/mysql
4. 生产环境单库备份
# 生产环境单库备份
mysqldump -ubackup_user -p -h127.0.0.1 -P3306 \
-B testdb --default-character-set=utf8mb4 \
--single-transaction --source-data=2 \
--triggers --events --routines \
--set-gtid-purged=off > /backup/mysql/`date +%Y%m%d`_0.sql
5. 完整实例备份
sqldump -ubackup_user -p -h127.0.0.1 -P3306 \
--all-databases --default-character-set=utf8mb4 \
--single-transaction --source-data=2 \
--triggers --events --routines \
--set-gtid-purged=off --flush-logs > /backup/mysql/`date +%Y%m%d`_1.sql
--all-databases:备份所有数据库;
--flush-logs:备份完刷新日志,以便后面做增量备份;
不推荐使用备份所有数据库,有的版本存在 bug,可能会导致某些系统表无法使用;
6. 单表多表备份
# 单表多表备份
mysqldump -ubackup_user -p -h127.0.0.1 -P3306 \
-B testdb --tables class student \
--default-character-set=utf8mb4 \
--single-transaction --source-data=2 \
--triggers --events --routines \
--set-gtid-purged=off > /backup/mysql/dump2.sql
7. 按条件备份
# 按条件备份
mysqldump -ubackup_user -p -h127.0.0.1 -P3306 \
-B testdb --tables class student --default-character-set=utf8mb4 \
--single-transaction --source-data=2 \
--triggers --events --routines --set-gtid-purged=off \
--where='id<3' > /backup/mysql/dump3.sql
8. 导出表结构
# 导出表结构
mysqldump -ubackup_user -p -h127.0.0.1 -P3306 \
-B testdb -d --default-character-set=utf8mb4 \
--single-transaction --source-data=2 \
--triggers --events --routines \
--set-gtid-purged=off > /backup/mysql/dump4.sql
--no-data, -d:不转储表内容;
9. 只备份数据
# 导出数据
mysqldump -ubackup_user -p -h127.0.0.1 -P3306 \
--databases testdb --hex-blob --no-create-db --no-create-info \
--default-character-set=utf8mb4 \
--single-transaction --source-data=2 \
--triggers --events --routines \
--set-gtid-purged=off --flush-logs > /backup/mysql/dump5.sql
10. 数据导入
命令行导入:
# 命令行导入
mysql -uroot -p < /backup/mysql/dump6.sql
交互式导入:
登录 mysql 客户端导入 sql 文件
mysql -uroot -p
password:mysql> source /backup/mysql/dump.sql
流式导入:
# 流式导入
mysqldump -ubackup_user -p123456@BitBit -h127.0.0.1 -P3306 \
-B testdb --default-character-set=utf8mb4 \
--single-transaction --source-data=2 \
--triggers --events --routines \
--set-gtid-purged=off | mysql -uroot -p123456 -h192.168.100.237 -P3306
11. 监控恢复进度
# 监控恢复进度
# Debian/Ubuntu 系统
sudo apt-get install pv# Red Hat/CentOS 系统
sudo yum install pv# 导⼊并查看进度
pv -L1000 /backup/mysql/dump6.sql | mysql -uroot -p123456 -h127.0.0.1 -P3306
4. 备份方法二:SQL 语句导出导入
MySQL 中可以通过 SQL 语句把查询出来的数据导出到服务器文件中,也可以从导出文件加载数据到指定的数据库和表,同时提供了一个导入工具,方便在命令行中完成导入操作;
1. 查看允许导出的目录:
-- 查看全局只读参数 secure_file_priv 的值(允许导出的⽬录)
show variables like 'secure_file_priv';
应用场景:
- 简单的数据备份和数据迁移;
- 将数据导出到外部应用程序进一步处理;
2. sql 语句导入导出
-- sql 语句备份
-- 导出
select * from db_name.tbl_name into outfile 'filename';
-- 导入
load data infile 'filename' into table tbl_name;-- 导入导出时设置字段顺序
-- 导出
select 列名1, 列名2, ... from db_name.tbl_name into outfile 'filename';
-- 导入
load data infile 'filename' into table tbl_name(列名1, 列名2, ...);
3. mysqlimport 导入
mysqlimport -uroot -p testdb /var/lib/mysql-files/student1.txt
注意:表名是跟导出的文件是通过名字匹配的;mysqlimport 会根据导入的文件名去匹配数据库中的表名;
5. 备份方法三:物理备份工具-Xtrabackup
Percona XtraBackup for MySQL - Top MySQL Backup Solution
应用场景:
- 大型数据库备份:可以节省存储空间和备份时间;
- 高可用环境:可以在不影响数据库服务的情况下进行在线热备份,适用于高可用环境的备份需求;
- 全量和增量备份:可以定期进行增量备份以节省存储空间和备份时间的场景;
- 全量和增量恢复:可以进行全量和增量恢复,甚至可以进行部分恢复和时间点恢复;
需根据 mysql 和 linux 版本确定 Xtrabackup 的版本;
1. 软件安装
# 数据库物理备份工具
# 安装软件源
dpkg -i percona-xtrabackup-80_8.0.35-31-1.jammy_amd64.deb# 更新源
apt update# 如果提⽰缺少依赖运⾏以下命令安装
apt-get install -f# 安装 xtrabackup
apt install percona-xtrabackup-80# 更新源
apt update# 安装 xtrabackup
apt install percona-xtrabackup-80# 验证是否成功
xtrabackup --version
2. 全量备份
确保 /etc/msyql/my.cnf 已配置好:
# 全量备份
xtrabackup --defaults-file=/etc/mysql/my.cnf \
--host=localhost --port=3306 --user=backup_user --password=123456 \
--use-memory=1G --parallel=2 \
--backup --target-dir=/backup/mysql/full
xtrabackup_binlog_info:记录备份时binlog⽇志和POS信息;
xtrabackup_checkpoints:备份类型和备份LSN信息,增量备份时依赖⽂件中的LSN;
xtrabackup_info:备份信息;
恢复:
# 停止 mysql 服务
systemctl stop mysql
# 查看 mysql 服务是否停止
systemctl status mysql# 数据目录改名
mv /var/lib/mysql /var/lib/mysql-old
# 创建空目录
mkdir -p /var/lib/mysql# 准备
xtrabackup --prepare --target-dir=/backup/mysql/full
# 恢复数据
xtrabackup --defaults-file=/etc/mysql/my.cnf --copy-back --parallel=2 --target-dir=/backup/mysql/full# 为恢复⽬录授权
chown -R mysql:mysql /var/lib/mysql# 启动 MySQL 服务
systemctl start mysql# 查看 MySQL 服务
systemctl status mysql
3. 增量备份
增量备份之前,需要进行一次全量备份,全量备份的过程同上;
# 增量备份
# 为当前增量备份指定保存备份的⽬录,以及全量备份的⽬录
xtrabackup --host=localhost --port=3306 --user=backup_user --password=123456 --backup --target-dir=/backup/mysql/inc1 --incremental-basedir=/backup/mysql/full# 为当前增量备份指定保存备份的⽬录,以及上⼀次增备的⽬录
xtrabackup --host=localhost --port=3306 --user=backup_user --password=123456 --backup --target-dir=/backup/mysql/inc2 --incremental-basedir=/backup/mysql/inc1# 增量恢复
# 准备全量恢复
xtrabackup --prepare --apply-log-only --target-dir=/backup/mysql/full# 准备第一次增量恢复
xtrabackup --prepare --apply-log-only --target-dir=/backup/mysql/full --incremental-dir=/backup/mysql/inc1# 准备第二次增量恢复
xtrabackup --prepare --target-dir=/backup/mysql/full --incremental-dir=/backup/mysql/inc2# 恢复数据
xtrabackup --copy-back --parallel=2 --target-dir=/backup/mysql/full# 为恢复⽬录授权
chown -R mysql:mysql /var/lib/mysql
# 启动 MySQL 服务
systemctl start mysql
# 查看 MySQL 服务
systemctl status mysql