跳转至

MySQL备份1 ----- 逻辑备份

备份恢复(重点内容)

运维的备份恢复相关职责:

  • 设计备份策略
  • 日常备份
  • 恢复演练
  • 故障恢复
  • 迁移

一. 备份类型

热备:在数据库正常业务中备份数据并且能够一次性恢复(只能是innodb)

冷备:关闭数据库业务,数据库没有任何变更的情况下,进行备份数据。

温备:锁表备份,只能查询不能修改(myisam)

二. 备份方式及工具介绍

1. 逻辑备份工具:基于SQL语句进行备份

mysqldump *****

mysqlbinlog *****

2. 物理备份工具:基于磁盘数据文件备份

xtrabackup (XBK) percona 第三方 *****

MySQL Enterprise Backup(MEN)

3. 逻辑备份与物理备份的比较

mysqldump ----- 自带逻辑备份工具

a. 优点:

  • 不需要下载安装额外服务
  • 备份出来的是SQL,文本格式,可读性更高,便于备份处理
  • 压缩比高,节省备份的磁盘空间

b. 缺点:

  • 依赖于数据库引擎(InnoDB可以实现热备份,myisam只能实现温备份),需要从磁盘中把数据读出来,然后转换成SQL进行转储,比较耗费资源,数据量大的话效率较低。

c. 建议:

100G以内的数据量级可以使用mysqldump,备份/恢复大概需要20-40分组

超过1TB以上,我们可以选择的是mysqldump,配合分布式系统

4. xtrabackup(XBK)---第三方物理备份工具

a. 优点:

  • 类似于直接复制(cp)文件,不需要关逻辑结构,相对来说性能较高。

b. 缺点:

  • 可读性差
  • 压缩比低,需要更多磁盘空间

c. 建议:

使用xtrabackup备份的数据建议在100GB左右,低于1TB

三. 备份策略

全备份:全库备份,备份所有的数据

增量备份:备份变化的数据

比如:周日全备份,周一到周六增量备份

四. mysqldump(逻辑备份的客户端工具)

1. 客户端的通用参数

  • -u:用户名
  • -p:端口号
  • -S:socket文件
  • -h:数据库的IP地址
  • -p:密码

mysqldump -uroot -p

2. 备份专用的基本参数

(1) -A 全备份

全备份参数:

例子一 --- 全备份:

[root@4 ~]# mkdir /backup
[root@4 ~]# mysqldump -uroot -p -A>/backup/full.sql
Enter password: 

(2) -B db1、db2、db3备份多个单库

例子2 --- 单库或多库备份,比较熟褐与跨版本的迁移,只备份生产库

[root@4 ~]# mysql -uroot -p -B test world >/backup/bak.sql

(3) 备份单个或多个表

例子3---world数据库下的city表、country表

[root@4 ~]# mysqldump -uroot -p world city country>/backup/bak1.sql

* 注意:-B的作用

  • mysqldump -uroot -p -B world>/backup/test.sql
  • mysqldump -uroot -p world>/backup/test1.sql

以上两个语句都可以备份world数据库下的所有表

-B添加了create database和use

所以和库相关的备份一般需要加-B

(4) 特殊参数1使用

-R 备份存储过程和函数

--triggers备份触发器

[root@4 ~]# mysqldump -uroot -p -A -R -triggers>/backup/full.sql

(5) 特殊参数2使用

++++++++++++++++++++++++++++++++++++++++

每天晚上12点全备份

上午十点数据库被误删除了

二进制日志截取将称为我们比较棘手的问题

起点:怎么办

终点:怎么找

++++++++++++++++++++++++++++++++++++++++

(6) -F在备份开始时,刷新一个新的binlog日志

例子5:

[root@4 ~]# mysqldump -uroot -P -A -R --triggers -F>/backup/full.sql

(7) --source-data=2

以注释的形式保存备份开始时间点的binlog的状态信息

[root@4 ~]# mysqldump -uroot -p -A -R --triggers --source-data=2>/backup/full.sql

0 默认值

1 以change replication source to 命令形式,可以做主从复制

2 以注释的形式记录,备份时刻的二进制文件名+postion号

single-transaction可以加锁

  • 不加--single-transaction,启动所有表的温备份,所有表锁定
  • 加上--single-transcation,对innodb可以不锁表热备份,对非innodb表可以实现自动锁表功能

例子6:备份必加参数 生产使用

[root@4 ~]# mysqldump -uroot -p -A -R -triggers --source-data=2 --single-transaction>/backup/full.sql

功能:

  • (1)以注释的形式保存备份开始时间点的binlog状态信息
  • (2)对innodb可以不锁表热备份
  • (3)对非innodb表可以实现自动锁表的功能

五. 使用mysqldump+mysqlbinlog进行1逻辑备份及恢复

1. 模拟故障案例并恢复

  • (1)晚上全备份
  • (2)binlog日志是完整的
  • (3)模拟白天的数据变化
  • (4)模拟下午两点误删数据库

开启二进制日志

[root@3 data]# vi /etc/my.cnf

[client]
socket = /usr/local/mysql/mysql.sock        #客户连接使用的socket

[mysqld]
server_id=10                                #将这台 MySQL 服务器的 ID 指定为 10
port = 3306                                 #默认监听的端口为3306
user = mysql                                #mysql进程的维护用户为mysql
character-set-server = utf8mb4              #默认字符集
default_storage_engine = innodb             #默认存储引擎
log_timestamps = SYSTEM                     #日志时间戳使用系统时间
socket = /usr/local/mysql/mysql.sock        #服务端的socket文件存放的位置
basedir = /usr/local/mysql                  #mysql的安装目录
datadir = /data/mysql/data                  #mysql数据文件的存放目录
pid-file = /usr/local/mysql/mysql.pid       #mysql进程id存放位置
log_error = /data/mysql/log/mysql-error.log #mysql错误日志的存放位置
sql_mode='ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION'
#STRICT_TRANS_TABLES 严格模式核心 — 对事务表启用严格模式,插入/更新数据时若值无效(如类型错误、超出长度),直接报错而非发出警告
#NO_ZERO_IN_DATE 不允许月份或日为零的日期,例如 '2010-00-01'、'2024-01-00' 会被拦截。现已被废弃,但不会报错
# 不允许 '0000-00-00' 作为合法日期。现已被废弃,但不会报错
#ERROR_FOR_DIVISION_BY_ZERO 除零操作直接报错,而非返回 NULL 并给警告
#NO_ENGINE_SUBSTITUTION 建表时如果指定了被禁用的存储引擎(如 Memory 被禁用),直接报错,而非自动替换为默认引擎(InnoDB)
skip-name-resolve                           #跳过DNS反向解析
innodb_print_all_deadlocks = 1
log_bin = /data/mysql/log/binlog         #开启二进制文件

[root@3 data]# systemctl restart mysqld

Ⅰ. 模拟晚上全备份

[root@4 data]# cd
[root@4 ~]#mysql -e 'CREATE DATABASE uuu'&& mysql -e 'SHOW DATABASES'
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| sys                |
| uuu                |
+--------------------+
[root@4 ~]# mkdir /bak
[root@4 ~]# mysqldump -uroot -p -A -R --triggers --master-data=2 --single-transaction>/bak/full.sql
WARNING: --master-data is deprecated and will be removed in a future version. Use --source-data instead.
Enter password: 
#或
[root@4 ~]#  mysqldump -uroot -p -A -R --triggers --source-data=2 --single-transaction>/bak/full.sql
Enter password: 
[root@4 ~]# ls /bak
full.sql

Ⅱ. 模拟白天的数据操作变化:

a. 准备数据

[root@4 ~]# mysql -uroot -p
Enter password: 
mysql> DROP DATABASE IF EXISTS test;
Query OK, 1 row affected, 1 warning (0.01 sec)

mysql> CREATE DATABASE test;
Query OK, 1 row affected (0.00 sec)

mysql> USE test;
Database changed

mysql> CREATE TABLE stu(id int);
Query OK, 0 rows affected (0.01 sec)

mysql> INSERT INTO stu VALUES(1),(2),(3),(4);
Query OK, 4 rows affected (0.00 sec)
Records: 4  Duplicates: 0  Warnings: 0

mysql> commit;
Query OK, 0 rows affected (0.00 sec)

mysql> UPDATE stu SET id=30 WHERE id=3;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 0

mysql> DELETE FROM stu WHERE id=4;
Query OK, 1 row affected (0.00 sec)

mysql> INSERT INTO stu VALUES(6),(7),(8);
Query OK, 3 rows affected (0.00 sec)
Records: 3  Duplicates: 0  Warnings: 0

mysql> COMMIT;
Query OK, 0 rows affected (0.00 sec)

mysql> SELECT * FROM stu;
+------+
| id   |
+------+
|    1 |
|    2 |
|   30 |
|    6 |
|    7 |
|    8 |
+------+
6 rows in set (0.00 sec)

mysql> exit
Bye

b. 破坏数据---模拟下午两点误删数据库

[root@4 ~]# ls /data/mysql/data
 auto.cnf     client-cert.pem     '#ib_16384_1.dblwr'  '#innodb_redo'   mysql.ibd               private_key.pem   server-key.pem   undo_001
 ca-key.pem   client-key.pem       ib_buffer_pool      '#innodb_temp'   mysql_upgrade_history   public_key.pem    sys              undo_002
 ca.pem      '#ib_16384_0.dblwr'   ibdata1              mysql           performance_schema      server-cert.pem   test             uuu
[root@4 ~]# rm -rf /data/mysql/data/*
[root@4 ~]# ls /data/mysql/data
[root@4 ~]# systemctl stop mysqld

c. 恢复

(0). 初始化数据库并启动服务

[root@4 ~]# rm -rf /data/mysql/data/*
[root@4 ~]# mysqld --initialize-insecure --user=mysql --basedir=/usr/local/mysql --datadir=/data/mysql/data
[root@4 ~]# ls /data/mysql/data
 auto.cnf         '#ib_16384_0.dblwr'  '#innodb_temp'           private_key.pem   undo_001
 ca-key.pem       '#ib_16384_1.dblwr'   mysql                   public_key.pem    undo_002
 ca.pem            ib_buffer_pool       mysql.ibd               server-cert.pem
 client-cert.pem   ibdata1              mysql_upgrade_history   server-key.pem
 client-key.pem   '#innodb_redo'        performance_schema      sys
[root@3 ~]# systemctl start mysqld

(1). 恢复昨晚全备份

[root@3 ~]# mysql

mysql> set sql_log_bin=0;
Query OK, 0 rows affected (0.00 sec)

mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| sys                |
+--------------------+
4 rows in set (0.01 sec)

mysql> source /bak/full.sql;

mysql>  show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| sys                |
| uuu                |
+--------------------+
5 rows in set (0.00 sec)

mysql> quit
Bye

(2). 找到binlog并截取(起点,终点)恢复

在全部的sql文件中找到binlog文件

[root@4 ~]# cat /bak/full.sql|grep '\-\- CHANGE REPLICATION'
-- CHANGE REPLICATION SOURCE TO SOURCE_LOG_FILE='binlog.000002', SOURCE_LOG_POS=340;

使用mysqlbinlog命令查看并寻找截取的起点和终点

[root@4 ~]# cd /data/mysql/log
[root@4 log]# mysqlbinlog -v binlog.000002
# The proper term is pseudo_replica_mode, but we use this compatibility alias
# to make the statement usable on server versions 8.0.24 and older.
/*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=1*/;
/*!50003 SET @OLD_COMPLETION_TYPE=@@COMPLETION_TYPE,COMPLETION_TYPE=0*/;
DELIMITER /*!*/;
# at 4
#260706 17:53:11 server id 10  end_log_pos 127 CRC32 0x8e72ab79     Start: binlog v 4, server v 8.4.10 created 260706 17:53:11 at startup
ROLLBACK/*!*/;
BINLOG '
B3tLag8KAAAAewAAAH8AAAAAAAQAOC40LjEwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAHe0tqEwANAAgAAAAABAAEAAAAYwAEGggAAAAAAAACAAAACgoKKioAEjQA
CigAAAF5q3KO
'/*!*/;
...
### DELETE FROM `test`.`stu`
### WHERE
###   @1=4
# at 1717
#260706 17:56:33 server id 10  end_log_pos 1748 CRC32 0x89f20533    Xid = 678
COMMIT/*!*/;
...
# at 1951
#260706 17:56:37 server id 10  end_log_pos 2001 CRC32 0xe8993571    Write_rows: table id 179 flags: STMT_END_F

BINLOG '
1XtLahMKAAAAMQAAAJ8HAAAAALMAAAAAAAEABHRlc3QAA3N0dQABAwABAQEAzOX6Ow==
1XtLah4KAAAAMgAAANEHAAAAALMAAAAAAAEAAgAB/wAGAAAAAAcAAAAACAAAAHE1meg=
'/*!*/;
### INSERT INTO `test`.`stu`
### SET
###   @1=6
### INSERT INTO `test`.`stu`
### SET
###   @1=7
### INSERT INTO `test`.`stu`
### SET
###   @1=8
# at 2001
#260706 17:56:37 server id 10  end_log_pos 2032 CRC32 0x2d4740ae    Xid = 679
COMMIT/*!*/;
# at 2032
#260706 17:57:43 server id 10  end_log_pos 2055 CRC32 0x58968323    Stop
SET @@SESSION.GTID_NEXT= 'AUTOMATIC' /* added by mysqlbinlog */ /*!*/;
DELIMITER ;
# End of log file
/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;
/*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=0*/;
[root@4 log]# mysqlbinlog --start-position=340 --stop-position=1717 binlog.000002|mysql
[^_^] [root@4 log]#mysql -e 'use test;select * from stu;'
+------+
| id   |
+------+
|    1 |
|    2 |
|   30 |
|    4 |
+------+

从1717位置到最后将678数据恢复

[root@4 log]# mysqlbinlog --start-position=1717 binlog.000002|mysql
[root@4 log]# mysql -e 'use test;select * from stu;'
+------+
| id   |
+------+
|    1 |
|    2 |
|   30 |
|    4 |
|    6 |
|    7 |
|    8 |
+------+

重启mysql服务后登录数据库密码就变回备份前的了

[^_^] [root@4 log]#systemctl kill mysqld
[^_^] [root@4 log]#systemctl start mysqld
[^_^] [root@4 log]#ss -tuanp |grep 3306
tcp   LISTEN 0      151                  *:3306                *:*     users:(("mysqld",pid=1789,fd=21))                    
tcp   LISTEN 0      70                   *:33060               *:*     users:(("mysqld",pid=1789,fd=18))  

(3). 利用时间截取二进制日志

如

mysqlbinlog -start-datetime="2026-05-17 16:20:54" --stop-datetime="2026-05-17 17:19:12" /data/mysql/log/mysql-bin.000003