MySQL数据库备份与恢复

系列文章目录

MySQL的基础操作-CSDN博客

MySQL操作进阶-CSDN博客

MySQL索引事务-CSDN博客

MySQL的JDBC编程-CSDN博客

MySQL存储过程和触发器_mysql 存储过程-CSDN博客

数据库设计简述-CSDN博客


目录

系列文章目录

文章目录

前言

[一、MySQL 日志](#一、MySQL 日志)

二、二进制日志

[1. 介绍](#1. 介绍)

[2. 作用](#2. 作用)

[3. 配置](#3. 配置)

[4. 磁盘文件](#4. 磁盘文件)

[5. 日志格式](#5. 日志格式)

[6. 刷盘策略](#6. 刷盘策略)

[7. mysqlbinlog 工具](#7. mysqlbinlog 工具)

[8. 远程备份 binlog 日志](#8. 远程备份 binlog 日志)

三、备份

[1. 分类](#1. 分类)

[2. 备份方法一:Mysqldump 工具](#2. 备份方法一:Mysqldump 工具)

[3. Mysqldump 备份完整过程](#3. Mysqldump 备份完整过程)

[1. 备份之前,需收集信息,确保备份内容完整:](#1. 备份之前,需收集信息,确保备份内容完整:)

[2. 创建备份用户及授权:](#2. 创建备份用户及授权:)

[3. 创建备份目录](#3. 创建备份目录)

[4. 生产环境单库备份](#4. 生产环境单库备份)

[5. 完整实例备份](#5. 完整实例备份)

[6. 单表多表备份](#6. 单表多表备份)

[7. 按条件备份](#7. 按条件备份)

[8. 导出表结构](#8. 导出表结构)

[9. 只备份数据](#9. 只备份数据)

[10. 数据导入](#10. 数据导入)

[11. 监控恢复进度](#11. 监控恢复进度)

[4. 备份方法二:SQL 语句导出导入](#4. 备份方法二:SQL 语句导出导入)

[1. 查看允许导出的目录:](#1. 查看允许导出的目录:)

[2. sql 语句导入导出](#2. sql 语句导入导出)

[3. mysqlimport 导入](#3. mysqlimport 导入)

[5. 备份方法三:物理备份工具-Xtrabackup](#5. 备份方法三:物理备份工具-Xtrabackup)

[1. 软件安装](#1. 软件安装)

[2. 全量备份](#2. 全量备份)

[3. 增量备份](#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 相关的系统变量:

sql 复制代码
-- 查看包含 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 中:

bash 复制代码
# 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),也会保证事务的完整性;

删除二进制日志文件:

sql 复制代码
-- 删除指定日志文件之前的所有日志文件并更新索引
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:停止解码的位置;

语法:

bash 复制代码
# 查看日志
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

通过二进制日志恢复数据:

bash 复制代码
# 数据库恢复
# 方法一:找到恢复的起始位置,直接通过二进制日志进行恢复
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 日志

在主服务器上创建账号:

sql 复制代码
-- 远程备份 binlog 日志
-- 创建一个用于复制日志的用户
create user 'binloggrep'@'%' identified with mysql_native_password by '123456';
-- 为用户赋予复制权限
grant replication slave on *.* to 'binloggrep'@'%';
-- 刷新权限
flush privileges;
-- 测试登录
mysql -ubinloggrep -p123456

从服务器运行备份:

bash 复制代码
# 从服务器运行备份
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:转储每个表中的触发器;

bash 复制代码
# 导出本地数据库中所有数据到磁盘
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. 备份之前,需收集信息,确保备份内容完整:

sql 复制代码
-- 查看数据库的表信息
select
    table_schema,
    table_name,
    table_collation,
    ENGINE,
    table_rows 
FROM
    information_schema.TABLES 
WHERE
    table_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. 创建备份用户及授权:

sql 复制代码
-- 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. 创建备份目录

bash 复制代码
mkdir -p /backup/mysql

4. 生产环境单库备份

bash 复制代码
# 生产环境单库备份
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. 完整实例备份

bash 复制代码
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. 单表多表备份

bash 复制代码
# 单表多表备份
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. 按条件备份

bash 复制代码
# 按条件备份
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. 导出表结构

bash 复制代码
# 导出表结构
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. 只备份数据

bash 复制代码
# 导出数据
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. 数据导入

命令行导入:

bash 复制代码
# 命令行导入
mysql -uroot -p < /backup/mysql/dump6.sql

交互式导入:

bash 复制代码
登录 mysql 客户端导入 sql 文件
mysql -uroot -p
password:

mysql> source /backup/mysql/dump.sql

流式导入:

bash 复制代码
# 流式导入
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. 监控恢复进度

bash 复制代码
# 监控恢复进度
# 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. 查看允许导出的目录:

sql 复制代码
-- 查看全局只读参数 secure_file_priv 的值(允许导出的⽬录)
show variables like 'secure_file_priv';

应用场景:

  • 简单的数据备份和数据迁移;
  • 将数据导出到外部应用程序进一步处理;

2. sql 语句导入导出

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 导入

bash 复制代码
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. 软件安装

bash 复制代码
# 数据库物理备份工具
# 安装软件源
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 已配置好:

bash 复制代码
# 全量备份
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:备份信息;

恢复:

bash 复制代码
# 停止 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. 增量备份

增量备份之前,需要进行一次全量备份,全量备份的过程同上;

bash 复制代码
# 增量备份
# 为当前增量备份指定保存备份的⽬录,以及全量备份的⽬录
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

相关推荐
听雪楼主.3 分钟前
Oracle Undo Tablespace 使用率暴涨案例分析
数据库·oracle·架构
我科绝伦(Huanhuan Zhou)4 分钟前
KINGBASE集群日常维护管理命令总结
数据库·database
妖灵翎幺9 分钟前
Java应届生求职八股(2)---Mysql篇
数据库·mysql
HMBBLOVEPDX12 分钟前
MySQL的事务日志:
数据库·mysql
wml000003 小时前
CentOS启动两个MySQL实例
mysql·centos·3406
专注API从业者4 小时前
基于 Flink 的淘宝实时数据管道设计:商品详情流式处理与异构存储
大数据·前端·数据库·数据挖掘·flink
小猿姐5 小时前
KubeBlocks for Milvus 揭秘
数据库·云原生
AI 嗯啦5 小时前
SQL详细语法教程(四)约束和多表查询
数据库·人工智能·sql
杜子不疼.5 小时前
《Python学习之文件操作:从入门到精通》
数据库·python·学习