mysqldump备份

1.mysqldump备份原理

mysqldump备份过程

可以临时性的general log,备份完成后观察整个日志中的备份过程

flush tables;关闭所有打开的表

flush tables with read lock;加全局读锁

set session transaction isolation level repeatable read; 将隔离级别转为RR

start transaction; 开启事务

show master status; 获取正在使用的二进制文件

unlock tables; 释放全局读锁,这时就可以做写操作

show create database db;

savepoint sp; 回滚点

show create table t1;

select * from t1;

rollback to sp; 回滚到sp回滚点

release savepoint sp;

mysqldump的备份原理:通过设置READ LOCK获取数据库全局锁后,RR事务隔离级别下记录当前的日志文件名和日志位置position,然后释放掉全局锁。接下来创建一个事务的回滚点,所有数据的获取都是获取的是这个sp回滚点数据。最后释放掉回滚点sp。当然,对于MyISAM存储引擎,备份是直接锁全表的。

值得注意点:从分析mysqldump过程中我们可以知道,此命令在开始时刻会带来数据库瞬时的锁定(FLUSH TABLES WITH READ LOCK),虽然锁定时间是非常短暂的,但是却会带来非常大的数据库隐患,因为在此过程中,如果执行有DDL语句,就会导致此命令堵塞并最终异常退出。所以在做备份时间节点的选择上,需要根据数据库环境选择在负载压力最小,且没有以上操作时候进行备份。

1.1备份类型

热备

在数据库正常业务时,备份数据,并且能够一致性恢复(只能是innodb)
对业务影响非常小

温备

锁表备份,只能查询不能修改(myisam)
影响到写入操作

冷备

关闭数据库业务,数据库没有任何变更的情况下,进行备份数据.
业务停止

1.2备份方式

逻辑备份
基于SQL语句进行备份
mysqldump *****
mysqlbinlog *****

物理备份
基于磁盘数据文件备份
xtrabackup(XBK) :percona 第三方 *****
MySQL Enterprise Backup(MEB)

1.3逻辑备份和物理备份的比较

mysqldump (MDP)

优点:
1.不需要下载安装
2.备份出来的是SQL,文本格式,可读性高,便于备份处理
3.压缩比较高,节省备份的磁盘空间

缺点:
4.依赖于数据库引擎,需要从磁盘把数据读出
然后转换成SQL进行转储,相当耗费资源,数据量大的话效率较低
建议:
50G以内的数据量级,可以使用mysqldump

xtrabackup(XBK)

优点:
1.类似于直接cp数据文件,不需要管逻辑结构,相对来说性能较高
缺点:
2.可读性差
3.压缩比低,需要更多磁盘空间
建议:
>50G<TB

2.mysqldump常用参数

官网参数查询:https://dev.mysql.com/doc/refman/5.7/en/mysqldump.html

参数名 缩写 含义 默认值
--user -u 连接服务器时使用的账户
--password -p 密码
--port -P 端口号 3306
--all-database -A 备份mysql上的所有库
--database -B 备份指定的库
--add-drop-database 每个数据库创建之前添加drop数据库语句 未开启
--add-drop-table 创建表之前添加drop语句 开启
--events -E 导出事件 未开启
--routines -R 导出存储过程及自定义函数 未开启
--triggers 导出触发器 开启
--extended-insert -e 使用具有多个values列的insert语法 开启
--ignore-table 不导出指定表,指定忽略多个表时,需要重复指定多次
--no-data -d 不导出任何数据,只会导出数据库表结构
--no-create-info -t 指导出数据,而不添加create table语句
--force -f 在导出过程中忽略出现的sql错误 未开启
--tz-utc 在导出顶部设置时区TIME_ZONE='+00:00' 开启
--where -w 只转储给定的where条件选择的记录
--set-gtid-purged 备份文件中是否添加SET @@GLOBAL.GTID_PURGED输出
--single-transaction 通过在一个事务中导出所有表从而创建一个一致性的快照,使用于innodb引擎
--master-data 该选项将当前服务器的binlog的位置和文件名追加到输出文件中。如果为1,将会输出CHANGE MASTER命令;如果为2,将会注释CHANGE MASTER

基本参数

-A 备份当前实例下所有的数据库

-B 备份指定的数据库

备份某个库的某些表: 库名 table1 table2 备份库中的指定表

-E 备份事件

-R 备份存储过程和函数

--triggers 备份触发器

--master-data=2 备份时记录当时的position号或者gtid号;这个position就是起始位置(为2注释这一行,不然影响手动重构主从)

--single-transaction 触发一致性备份(一个事务REPEATABLE READ中导出数据,确保产生一致性的备份数据,相当于一次性快照,对innodb能确保一致性,)

--set-gtid-purged=on 主从复制环境中需要,常规备份不需要

备份示例

备份文件的名称要有规范,例如:数据库+端口号+日期.sql

可以在备份时使用--flush-logs刷一下binlog,方便日后日用binlog

备份当前实例的所有库

mysqldump -uroot -p123456 -A -R -E --triggers --master-data=2 --flush-logs --single-transaction > ./all_3306_`date +%Y%m%d`.sql

备份当前实例下的指定数据库

-B 指定

mysqldump -uroot -p123456 -B db -R -E --triggers --master-data=2 --single-transaction > ./db_3306_`date +%Y%m%d`.sql

备份指定数据库中的一些表

dbname table1 table2 ...

mysqldump -uroot -p123456 db t1 -R -E --triggers --master-data=2 --single-transaction > ./db_t1_3306_`date +%Y%m%d`.sql

单独备份每个表

information_schema.tables

执行输出的脚本即可

select concat("mysqldump -uroot -p123 ",table_schema," ",table_name," --master-data=2 --single-transaction --set-gtid-purged=0  -R -E --triggers>/backup/",table_schema,"_",table_name,".sql") from information_schema.tables where table_schema not in ('sys','information_schema','performance_schema') into outfile '/var/lib/mysql-files/mysqldump.sh';

备份后压缩

示例:压缩备份

之后gzip -d解压即可

mysqldump -uroot -p123456 -A -R -E --triggers --master-data=2 --single-transaction | gzip -c > all_3306_`date +%Y%m%d`.sql.gz

示例:压缩备份在远程服务器

比如说我要备在129这台主机上

mysqldump -uroot -p123456 -A -R -E --triggers --master-data=2 --single-transaction | gzip -c | ssh root@192.168.190.129 'cat > /tmp/all_3306_`date +%Y%m%d`.sql.gz'

3.mysqldump恢复示例

案例:上午10点钟,因为误操作删库了,最近一次的全备是凌晨一点的。

思路:

​ 1.停止业务,防止二次伤害,flush-logs这样故障操作日志都在之前的binlog文件里

​ 2.用一个临时库,先恢复最近的全备

​ 3.截取从最近全备到10点删库之间的binlog,恢复到临时库,进行测试

方法一:直接将临时库顶替生产库

方法二:想误删的相关库和表导出,在导入到原生产库,测试后恢复业务

3.1准备昨天23点的全备

全备的同时--flush-logs

mysqldump -uroot -p123456 -A -R -E --triggers --master-data=2 --flush-logs --single-transaction > ./all_3306.sql

[root@localhost ~]# ls
all_3306.sql

#全备文件中截取的二级制文件位置
-- CHANGE MASTER TO MASTER_LOG_FILE='mysql-bin.000002', MASTER_LOG_POS=194;

3.2准备临时库

使用多实例的3307端口

systemctl start mysqld3307

3.3模拟昨天23点到10点之间的数据变化

use test
mysql> select * from t1;
+---+---+
| a | b |
+---+---+
| 1 | 1 |
| 2 | 1 |
+---+---+
2 rows in set (0.00 sec)

-- 插入数据模拟全备之后的数据变化
mysql> insert into t1 values(3,1),(4,1);
Query OK, 2 rows affected (0.08 sec)
Records: 2  Duplicates: 0  Warnings: 0

mysql> select * from t1;
+---+---+
| a | b |
+---+---+
| 1 | 1 |
| 2 | 2 |
| 3 | 1 |
| 4 | 1 |
+---+---+
4 rows in set (0.00 sec)


3.4删库

mysql> drop database test;
Query OK, 1 row affected (0.07 sec)

3.5将全备恢复到临时库

设置sql_log_bin=0,将之后的操作不写入binlog

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

mysql> source all_3306.sql;

-- 查看数据
mysql> use test;
mysql> select * from t1;
+---+---+
| a | b |
+---+---+
| 1 | 1 |
| 2 | 1 |
+---+---+
2 rows in set (0.00 sec)

3.6mysqlbinlog截取二进制日志

#在000003中,起始位置194
-- CHANGE MASTER TO MASTER_LOG_FILE='mysql-bin.000002', MASTER_LOG_POS=194;

#查看当前binlog位置,在000002文件
mysql> show master status\G
*************************** 1. row ***************************
             File: mysql-bin.000002
         Position: 618
     Binlog_Do_DB:
 Binlog_Ignore_DB:
Executed_Gtid_Set: 667ad4e0-fcc9-11eb-af3e-000c290c7222:1-5
1 row in set (0.00 sec)



#找到删除语句的位置526,stop-position会默认上一个
mysql> show binlog events in '/data/mysql/mysql3306/logs/mysql-bin.000002'\G


*************************** 9. row ***************************
   Log_name: mysql-bin.000002
        Pos: 526
 Event_type: Query
  Server_id: 1
End_log_pos: 618
       Info: drop database test
9 rows in set (0.00 sec)



#在原库截取二进制日志
[root@localhost ~]# mysqlbinlog --start-position=194 --stop-position=526 /data/mysql/mysql3306/logs/mysql-bin.000002 > db.sql

3.7将截取的sql,恢复到临时库进行测试

source db.sql;

mysql> select * from t1;
+---+---+
| a | b |
+---+---+
| 1 | 1 |
| 2 | 2 |
| 3 | 1 |
| 4 | 1 |
+---+---+
4 rows in set (0.01 sec)

3.8将故障的库或表导出,恢复到生产

将库导出

[root@localhost ~]# mysqldump -uroot -p123456 -P 3307 --set-gtid-purged=off -B test -R -E --triggers --master-data=2 --single-transaction > test_t1.sql

生产上恢复

mysql> source test_t1.sql;
mysql> select *  from  test.t1;
+---+---+
| a | b |
+---+---+
| 1 | 1 |
| 2 | 2 |
| 3 | 1 |
| 4 | 1 |
+---+---+
4 rows in set (0.00 sec)


4.关于mysqlbinlog使用

mysqlbinlog

语法:

恢复语法格式:
# mysqlbinlog mysql-bin.0000xx | mysql -u用户名 -p密码 数据库名
常用选项:
    ``--start-position=953          起始pos点
    ``--stop-position=1437          结束pos点
    ``--start-datetime=``"2017-6-20 13:18:54"`  `起始时间点
    ``--stop-datetime=``"2017-6-20 13:21:53"`  `结束时间点
    ``--database=juzidb            指定只恢复juzidb数据库(一台主机上往往有多个数据库,只限本地log日志)
      
不常用选项:  
    ``-u --user=name       Connect to the remote server ``as` `username.连接到远程主机的用户名
    ``-p --password[=name]    Password to connect to remote server.连接到远程主机的密码
    ``-h --host=name       Get the binlog ``from` `server.从远程主机上获取binlog日志
    ``--read-``from``-remote-server  Read binary logs ``from` `a MySQL server.从某个MySQL服务器上读取binlog日志

按时间段查看

对于MIXED(部分SQL语句)和ROW模式是以base-64方式记录,SQL部分会显示为base64编码,要正常显示还得加上两个参数:

-v --base64-output=DECODE-ROWS

--database=test 指定库

mysqlbinlog -v --base64-output=DECODE-ROWS --start-datetime="2021-08-18 09:00:00" --stop-datetime="2021-08-18 12:00:00" --database=test /data/mysql/mysql3306/logs/mysql-bin.000002

show binlog events in

使用show binlog events in查看找到pos

mysql -S /data/mysql/mysql3306/mysql.sock -e "show binlog events in '/data/mysql/mysql3306/logs/mysql-bin.000002'\G" > test.binlog

#太大的binlog不适合这样

语法:

 show binlog events 
 	[IN 'log_name'] 
 	[FROM pos] 
 	[LIMIT [offset,] row_count];
	

选项解析:
       IN 'log_name'   指定要查询的binlog文件名(不指定就是第一个binlog文件)
       FROM pos        指定从哪个pos起始点开始查起(不指定就是从整个文件首个pos点开始算)
       LIMIT [offset,] 偏移量(不指定就是0)
       row_count       查询总条数(不指定就是所有行)

示例;

A.查询第一个(即mysql-bin.000001)的binlog日志:

mysql> show binlog events\G

B.指定查询 mysql-bin.00002 这个文件:

mysql> show binlog events ``in` `'mysql-bin.000002'``\G

C.指定查询 mysql-bin.000002 这个文件,从pos点:534620开始查起:

mysql> show binlog events ``in` `'mysql-bin.000002'` `from` `534620\G

D.指定查询 mysql-bin.000002 这个文件,从pos点:534620开始查起,查询10条

mysql> show binlog events ``in` `'mysql-bin.000002'` `from` `534620 limit 10\G

E.指定查询 mysql-bin.000002 这个文件,从pos点:534620开始查起,偏移2行,查询10条

mysql> show binlog events ``in` `'mysql-bin.000002'` `from` `534620 limit 2,10\G

5.根据mysqldump全备中获取库和表的备份

1、获得表结构
# sed -e'/./{H;$!d;}' -e 'x;/CREATE TABLE `city`/!d;q'  full.sql>createtable.sql

2、获得INSERT INTO 语句,用于数据的恢复

# grep -i 'INSERT INTO `city`'  full.sqll >data.sql &

3.获取单库的备份

# sed -n '/^-- Current Database: `world`/,/^-- Current Database: `/p' all.sql >world.sql


6.binlog的备份

nohup mysqlbinlog -h192.168.190.128 -uroot -p123456 -P3306 -R --raw --stop-never mysql-bin.000001 &

异步备份;在主从环境中,推荐连接到主库备份主库的binlog

参数说明:

​ -u -p -h -P 连接指定的数据库

​ -R或--read-from-remote-server:开启binlog备份,并在指定的节点上拷贝binlog到本地

​ --raw:被拷贝过来的binlog保存方式是二进制方式

​ --stop-never:持续从指定节点上拉取binlog

​ mysql-bin.000001:从哪个binlog开始备份

停止备份:

ps -ef |grep mysqlbinlog

kill 进程号

posted @ 2021-08-24 13:42  EverEternity  阅读(691)  评论(0编辑  收藏  举报