Mysql备份原理与工具mysqldump之--single-transaction,--master-data

MySQL备份原理


数据备份是数据安全的底线,在任何场景下面,无论是上线后的数据回滚,数据丢失都能够有效的止损,将损失降到最低程度。

衡量数据备份与恢复的两个重要指标:

对于MySQL备份主要分为以下两种:

热备又分为两种:

快照备份:LVM使用写时复制(copy-on-write)技术来创建快照

例如对整个卷的某个瞬时的逻辑副本,类似于数据库中的innodb存储引擎的MVCC,只不过LVM的快照在文件系统层面,而MVCC在数据库层面,而且仅仅支持innodb存储引擎。

LVM有一个快照预留区域,如果原始数据有变化时,LVM保证在任何变更写入之前会复制受影响块到快照预留区域。

简单来说,快照区域内保存了快照开始时候的一致的所有old数据,对于更新很少的数据库,快照也会非常小。

对于MySQL而言,为了使用快照备份,需要将数据文件,日志文件都存放在一个逻辑卷中,然后对该卷做备份即可。

快照备份更偏向于对误操作防范,可以将数据库迅速恢复到快照产生的时间点,然后结合二进制日志可以恢复到指定的时间点。

逻辑备份

冷备份和快照备份由于其弊端在生产环境很少使用,使用更多的是MySQL自带的逻辑备份工具和物理备份工具。

MySQL官方虽然通过了MySQLdump逻辑备份工具,虽然已经足够用了,但是存在单线程备份慢的问题。

在社区提供了更加优秀的逻辑备份工具mysqldumper,它的优势主要体现在多线程备份,备份的速度更加快。

mysqldump工具


MySQLdump备份不得不提的两个关键参数

--single-transcation
--master-data=2

--master-data=2,--master-data=1 默认的话会--lock-all-tables,会锁住整个mysql数据库中的所有表。但是如果加上--single-transaction会加上事务,不会锁表

在mysqldump过程中,之前其实一直不是很理解为什么加了--single-transaction就能保证innodb的数据是完全一致的,而myisam引擎无法保证,必须加--lock-all-tables,前段时间抽空详细地查看了整个mysqldump过程。
理解master-data和--dump-slave

--master-data=2表示在dump过程中记录主库的binlog和pos点,并在dump文件中注释掉这一行;
--master-data=1表示在dump过程中记录主库的binlog和pos点,并在dump文件中不注释掉这一行,即恢复时会执行;

--dump-slave=2表示在dump过程中,在从库dump,mysqldump进程也要在从库执行,记录当时主库的binlog和pos点,并在dump文件中注释掉这一行;
--dump-slave=1表示在dump过程中,在从库dump,mysqldump进程也要在从库执行,记录当时主库的binlog和pos点,并在dump文件中不注释掉这一行;

注意:在从库上执行备份时,即--dump-slave=2,这时整个dump过程都是stop io_thread的状态

 关于mysqldump工作原理

一定要区别对待事务表innodb和非事务表myisam,因为备份流程与此息息相关。

注意:即使到目前为止,我们所有业务使用的表都是innodb,我们也无法规避myisam表,因为MySQL库中的系统表仍然采用的是myisam表。

备份流程如下:

1.调用FWRL(flush tables with read lock),全局禁止读写
2.开启快照读,获取此期间的快照(仅仅对innodb起作用)
3.备份非innodb表数据(*.frm,*.myi,*.myd等)
4.非innodb表备份完毕之后,释放FTWRL
5.逐一备份innodb表数据
6.备份完成

整个过程如图:

 

MySQLdump 备份时如何保持数据的一致性( –single-transaction)


 打开general_log

mysql> set global general_log=on;
mysql> show variables like '%general_log_file%';
+------------------+------------------------------+
| Variable_name    | Value                        |
+------------------+------------------------------+
| general_log_file | /var/lib/mysql/localhost.log |
+------------------+------------------------------+

打开general_log,开启备份,添加--single-transaction和--master-data=2参数,查看general_log,信息如下,每一步添加了我的理解 (此选项会将隔离级别设置为:REPEATABLE READ。并且随后再执行一条START TRANSACTION语句,让整个数据在dump过程中保证数据的一致性,这个选项对InnoDB的数据表很有用,且不会锁表)

备份整个库

[root@localhost backup]# mysqldump -uroot -proot -h127.0.0.1 --all-databases --single-transaction --routines --events --triggers --master-data=2 --hex-blob --default-character-set=utf8mb4 --flush-logs --quick > all.sql
mysqldump: [Warning] Using a password on the command line interface can be insecure.

 查看日志信息

[root@localhost ~]# tail -f  /var/lib/mysql/localhost.log
2020-06-20T06:27:31.809852Z	    5 Connect	root@localhost on  using SSL/TLS
2020-06-20T06:27:31.811401Z	    5 Query	/*!40100 SET @@SQL_MODE='' */
2020-06-20T06:27:31.812146Z	    5 Query	/*!40103 SET TIME_ZONE='+00:00' */
2020-06-20T06:27:31.812605Z	    5 Query	FLUSH /*!40101 LOCAL */ TABLES

2020-06-20T06:27:31.821019Z	    5 Query	FLUSH TABLES WITH READ LOCK
#批注:因为开启了--master-data=2,这时就需要flush tables with read lock锁住全库,记录当时的
#master_log_file和master_log_pos点

2020-06-20T06:27:31.821587Z	    5 Refresh	
/usr/sbin/mysqld, Version: 5.7.30-log (MySQL Community Server (GPL)). started with:
Tcp port: 3306  Unix socket: /var/lib/mysql/mysql.sock
Time                 Id Command    Argument


2020-06-20T06:27:31.827045Z	    5 Query	SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ
#批注:--single-transaction参数的作用,设置事务的隔离级别为可重复读,即REPEATABLE READ,这样能保证在一个事务中所有相同的查询读取到同样的数据,也就大概保证了在dump期间,如果其他innodb引擎的线程修改了表的数据并提交,对该dump线程的数据并无影响,然而这个还不够,还需要看下一条

2020-06-20T06:27:31.827934Z	    5 Query	START TRANSACTION /*!40100 WITH CONSISTENT SNAPSHOT */
#这时开启一个事务,并且设置WITH CONSISTENT SNAPSHOT为快照级别
想象一下,如果只是可重复读,那么在事务开始时还没dump数据时,这时其他线程修改并提交了数据,那么这时第一次查询得到的结果是其他线程提交后的结果
而WITH CONSISTENT SNAPSHOT能够保证在事务开启的时候,第一次查询的结果就是事务开始时的数据A,即使这时其他线程将其数据修改为B,查的结果依然是A

总结如下


MySQLdump 对不同类型的存储引擎,内部实现也不一样。主要是针对两种类型的存储引擎:支持事务的存储引擎(如 InnoDB )和不支持事务的存储引擎(如 MyISAM ),下面分别看看这两种存储引擎的实现:

1 、对于支持事务的引擎如 InnoDB , 参数上是在备份的时候加上 –single-transaction 保证数据一致性

–single-transaction 实际上通过做了下面两个操作 :

① 在开始的时候把该 session 的事务隔离级别设置成 repeatable read ;

② 然后启动一个事务(执行 begin ),备份结束的时候结束该事务(执行 commit )

有了这两个操作,在备份过程中,该 session 读到的数据都是启动备份时的数据(同一个点)。可以理解为对于 innodb 引擎来说加了该参数,备份开始时就已经把要备份的数据定下来了,备份过程中的提交的事务时是看不到的,也不会备份进去。

2 、对于不支持事务的引擎如 MyISAM ,只能通过锁表来保证数据一致性,这里分三种情况:

① 导出全库 : 加 –lock-all-tables 参数 , 这会在备份开始的时候启动一个全局读锁 ( 执行 flush tables with read lock ), 其他 session 可以读取但不能更新数据 , 备份过程中数据没有变化 , 所以最终得到的数据肯定是完全一致的 ;

② 导出单个库:加 –lock-tables 参数,这会在备份开始的时候锁该库的所有表,其他 session 可以读但不能更新该库的所有表,该库的数据一致;

猜你喜欢

转载自blog.csdn.net/qq_34556414/article/details/106781973#comments_21738069
今日推荐