1、mysqldump 介绍

  1. mysqldump 是一个逻辑备份工具 记录 (create database \ create table \ insert) 操作的SQL语句
  2. MySQL 自带的客户端命令、可以实现远程备份 (TCP连接) 本地备份(socket连接)

2、连接参数

-u  -p  -h  -P  -S

3、备份基本参数

-A: 全备

1. 本地备份:
mkdir -p /data/backup
格式:
mysqldump -uuser -ppassword -S mysql.sock 
举例:
mysqldump -uroot -p123 -S /tmp/mysql.sock -A > /data/backup/full.sql

2. 远程备份
格式:
mysqldump -user -ppassword -h 10.0.0.0 -P 3306
举例:     
mysqldump -uadmin -p123 -h 192.168.10.13 -P 3307 -A > /data/backup/full.sql    

3. 注意事项
使用 > 输出重定向, 不可改为 &>, 会把警告信息输入到sql文件, 造成无法恢复

-B: 备份单库或多库

格式:
mysqldump -uuser -ppassword -B 库1 库2 ...
举例:
mysqldump -uroot -p123 -B world test mysql > /data/backup/all.sql

备份单个表或者多个表

格式:
mysqldump -uuser -ppassword 库 表1 表2 ...
举例: world库下的city表
mysqldump -uroot -p123 world city  > world_city.sql
举例: world库下的city表和country表
mysqldump -uroot -p123 world city country  > world_city\&country.sql

4、备份高级参数

—master-data=2

功能1. 以注释的形式, 保存备份开始时间点的 binlog 的状态信息 # position号
  =0: 默认值
  =1: 以change master to 命令的形式,可以用作主从复制
  =2: 以注释的形式, 备份时刻的文件名+position号

功能2. 自动锁表

功能3. 如果配合 --single-transaction, 只对非InnoDB表进行锁表备份, InnnoDB表进行"热备", 实际上是实现快照备份

举例:
mysqldump -uroot -p123 -B world --master-data=2  > world.sql
grep 'CHANGE' /data/backup/world.sql

—single-transaction

InnoDB 存储引擎开启热备功能 (快照备份)
--master-data 可以自动加锁
  1.不加 --single-transaction, 启动所有表的温备份, 所有表都锁定
  2.加上 --single-transaction, 对 InnoDB 表进行快照备份, 对非 InnoDB 表可以实现自动锁表功能

举例:
mysqldump -uroot -p123 -B world --master-data=2  --single-transaction > world.sql
grep 'CHANGE' /data/backup/world.sql

理解: 将全班同学拍照, 然后数人数, 拍照完成大家可自由活动

—max_allowed_packet=64M

最大允许的数据包大小
mysqldump -uroot -p123 -B world --master-data=2  --single-transaction  --max_allowed_packet=64M  > world.sql

小故障: 备份时超出最大数据包大小
1153 - Got a packet bigger than 'max_allowed_packet' bytes

解决办法: --max_allowed_packet=64M # 乘以2倍逐个往上试

-R、-E、—triggers 备份特殊对象使用

-R, --routines: 存储过程和函数 # 相当于Linux系统的脚本
-E, --events: 事件 # 相当于Linux系统中的计划任务
--triggers: 触发器

#备份时都要加上, 否则备份的数据不完整
mysqldump -uroot -p123 -B world --master-data=2  --single-transaction  --max_allowed_packet=64M  -R -E --triggers > world.sql

格式化备份文件

mysqldump -uroot -p -B world --master-data=2  --single-transaction  --max_allowed_packet=64M  -R -E --triggers > world_`date +%F`.sql
#备份文件名: world_2021-02-19.sql

—set-gtid-purged=OFF

值: AUTO、ON、OFF
OFF: 使用场景 (备份, 恢复)
--set-gtid-purged=OFF, 可以使用在日常备份参数中
mysqldump -uroot -p -B world --master-data=2  --single-transaction  --max_allowed_packet=64M  -R -E --triggers --set-gtid-purged=OFF > world_`date +%F`.sql

AUTO、ON: 使用场景 (备份, 构建主从)
在构建主从复制环境时需要的参数配置
mysqldump -uroot -p -B world --master-data=2  --single-transaction  --max_allowed_packet=64M  -R -E --triggers --set-gtid-purged=ON > world_`date +%F`.sql

5、mysqldump 备份恢复应用

5.1、故障恢复演练 mysqldump + binlog (每天全备)

场景

mdp库是两年前创建的, 备份策略: 每天23:00进行全备, 周一23:00进行全备, 周二白天有数据写入, 下午误删除mdp库, 通过周一的全备和binlog进行数据恢复

模拟原始数据

create database mdp charset utf8mb4;
use mdp;
create table t1(id int);
insert into t1 values(1),(2),(3);
commit;

模拟每周一 23:00 的全备

mysqldump -uroot -p -A --master-data=2 --single-transaction --max_allowed_packet=64M -R -E --triggers > /data/backup/full_`date +%F`.sql

查看备份文件内容

#查看备份GTID相关信息, GTID截取起点
SET @@GLOBAL.GTID_PURGED='2e6ca7e0-45bd-11eb-bba7-000c2909345a:1-8237';

#查看备份position号相关信息, 备份开始时binlog和position
-- CHANGE MASTER TO MASTER_LOG_FILE='mysql-bin.000004', MASTER_LOG_POS=1102;

模拟周二白天数据变化

mysql> use mdp
mysql> insert into t1 values(4),(5),(6);
mysql> commit;

模拟周二下午14:00误删除了mdp核心库

drop database mdp;

5.2、故障恢复

1、恢复全备到周一23:00的数据

检查全备

vim vim full_2021-02-20.sql

# GTID
SET @@GLOBAL.GTID_PURGED='2e6ca7e0-45bd-11eb-bba7-000c2909345a:1-8237';
# position
-- CHANGE MASTER TO MASTER_LOG_FILE='mysql-bin.000004', MASTER_LOG_POS=1102;

2、截取日志

起点

#备份文件中记录的GTID,作为起点
#起点 GTID: '2e6ca7e0-45bd-11eb-bba7-000c2909345a:8237'
SET @@GLOBAL.GTID_PURGED='2e6ca7e0-45bd-11eb-bba7-000c2909345a:1-8237';

或者
#备份文件中记录的position,作为起点
#起点 position: 1102
-- CHANGE MASTER TO MASTER_LOG_FILE='mysql-bin.000004', MASTER_LOG_POS=1102;

终点
删库之前的position号

#通过 binlog 截取误删除时的GTID等信息
mysql -uroot -p123 -e "show binlog events in 'mysql-bin.000004'" | grep -B 1 "drop database mdp"

mysql-bin.000004    1363    Gtid    7    1428    SET @@SESSION.GTID_NEXT= '2e6ca7e0-45bd-11eb-bba7-000c2909345a:8239'
mysql-bin.000004    1428    Query    7    1517    drop database mdp

#终点: 通过 drop database mdp 时的GTID, 向前推一位     
GTID: 8239
position: 1363

进行 binlog 截取

mysqlbinlog --skip-gtids --include-gtids='2e6ca7e0-45bd-11eb-bba7-000c2909345a:8238-8238' /data/3307/binlog/mysql-bin.000004

3、恢复数据

set sql_log_bin=0;
source /data/backup/full_2021-02-20.sql
mysql> source /data/backup/bin.sql
set sql_log_bin=1;

4、检查数据

show databases;
use mdp
show tables;
+---------------+
| Tables_in_mdp |
+---------------+
| t1            |
+---------------+
mysql> select * from t1;

6、mysqldump 多种备份策略和恢复策略介绍

6.1、场景

100G 全库数据, 全库备份, 30-40分钟, 恢复整库要5倍时间, 2.5-3小时之间, 某张表 1G 被误删除了

6.2、mysqldump 备份策略

1、mysqldump 全备 + binlog 增量备份

 恢复单表数据思路:
1. 提取mysqldump全备中的故障表数据, 恢复数据
sed -n '/CREATE TABLE `oldguo` /,/\;/p' /data/backup/full.sql > /data/backup/create.sql
grep -i 'INSERT INTO `oldguo`'  /data/backup/full.sql > /data/backup/insert.sql

2. binlog 中截取全备到误删除表之间对于这张表的修改

2、单库单表备份 + binlog 增量备份

恢复单表数据思路:
1. 恢复单表的备份
2. binlog 中截取备份到误删除表之间对于这张表的修改

6.3、故障模拟

模拟原始数据

create database oldboy charset utf8mb4;
use oldboy;
create table oldguo (id int);
insert into oldguo values(1),(2),(3);
commit;

模拟周一23:00全备

mysqldump -uroot -p -A --master-data=2 --single-transaction --max_allowed_packet=64M -R -E --triggers > /data/backup/full.sql

模拟周二白天数据变化

use oldboy;
insert into oldguo values(11),(22),(33);
commit;
create table  oldli(id int);
insert into oldli values(1),(2),(3);
commit;
insert into oldguo values(111),(222),(333);
commit;
insert into oldli values(4),(5),(6);
commit;
insert into oldguo values(1111),(2222),(3333);
commit;

模拟周二下午14:00误删除了oldguo表

drop table  oldguo;

6.4、恢复过程

处理全备 # 截取建表、insert语句

#从全备中截取oldguo表建表语句
sed -n '/CREATE TABLE `oldguo` /,/\;/p' /data/backup/full.sql > /data/backup/create.sql

#从全备中截取oldguo表insert语句
grep -i 'INSERT INTO `oldguo`'  /data/backup/full.sql > /data/backup/insert.sql

binlog 截取

范围
起点: 通过备份文件记录信息

#起点GTID: 2e6ca7e0-45bd-11eb-bba7-000c2909345a:8259
SET @@GLOBAL.GTID_PURGED='2e6ca7e0-45bd-11eb-bba7-000c2909345a:1-8259';

终点: 通过 drop table 发生时的GTID截取

#终点GTID: 2e6ca7e0-45bd-11eb-bba7-000c2909345a:8265
mysql -uroot -p -e "show binlog events in 'mysql-bin.000007'" | grep -B 1 'DROP TABLE\ `oldguo`'

mysql-bin.000007    2503    Gtid    7    2568    SET @@SESSION.GTID_NEXT= '2e6ca7e0-45bd-11eb-bba7-000c2909345a:8266'
mysql-bin.000007    2568    Query    7    2691    use `oldboy`; DROP TABLE `oldguo` /* generated by server */

截取全备到误删除之前, oldguo表操作记录的GTID号

mysqlbinlog --include-gtids='2e6ca7e0-45bd-11eb-bba7-000c2909345a:8259-8265' /data/3307/binlog/mysql-bin.000007 | grep -B 8  '`oldboy`.`oldguo`' | grep 'GTID_NEXT'

SET @@SESSION.GTID_NEXT= '2e6ca7e0-45bd-11eb-bba7-000c2909345a:8260'/*!*/;
SET @@SESSION.GTID_NEXT= '2e6ca7e0-45bd-11eb-bba7-000c2909345a:8263'/*!*/;
SET @@SESSION.GTID_NEXT= '2e6ca7e0-45bd-11eb-bba7-000c2909345a:8265'/*!*/;

通过GTID号进行 binlog 截取

#方法一: 全部范围: 跳过不需要的GTID号
--include-gtids='100-200'
--exclude-gtids='150-160'  --exclude-gtids='180'  (跳过150-160,180) 
mysqlbinlog --skip-gtids --include-gtids='2e6ca7e0-45bd-11eb-bba7-000c2909345a:8260-8265' --exclude-gtids='2e6ca7e0-45bd-11eb-bba7-000c2909345a:8261-8262' --exclude-gtids='2e6ca7e0-45bd-11eb-bba7-000c2909345a:8264' /data/3307/binlog/mysql-bin.000007 > bin.sql

#方法二: 不连续的GTID,逐个添加,逗号分隔
--include-gtids='100-200'
--include-gtids='202'
mysqlbinlog --skip-gtids --include-gtids='2e6ca7e0-45bd-11eb-bba7-000c2909345a:8260','2e6ca7e0-45bd-11eb-bba7-000c2909345a:8263','2e6ca7e0-45bd-11eb-bba7-000c2909345a:8265' /data/3307/binlog/mysql-bin.000007 > /data/backup/bin.sql

恢复数据

use oldboy;
set sql_log_bin=0;
source /data/backup/create.sql
source /data/backup/insert.sql
commit;
source /data/backup/bin.sql
set sql_log_bin=1;

6.5、实现单库单表备份

mkdir -p /data/backup/tables
select concat("mysqldump -uroot -p123 --master-data=2 --single-transaction --max_allowed_packet=64M -R -E --triggers ",table_schema," ",table_name," > /data/backup/tables/",table_schema,"_",table_name,".sql") from information_schema.tables where table_schema not in ('sys','information_schema','performance_schema') into outfile '/tmp/tables.sh';
/bin/bash /tmp/tables.sh

可能遇到的报错:
ERROR 1290 (HY000): The MySQL server is running with the --secure-file-priv option so it cannot execute this statement

解决办法:
show variables like '%secure%';
vim /etc/my.cnf
secure-file-priv=''