http://www.cnblogs.com/ivictor/p/5505307.html

 

对于MySQL的备份,可分为以下两种:

1. 冷备

2. 热备

其中,冷备,顾名思义,就是将数据库关掉,利用操作系统命令拷贝数据库相关文件。而热备指的是在线热备,即在不关闭数据库的情况下,对数据库进行备份。实际生产中基本上都是后者。

关于热备,也可分为两种方式:

1. 逻辑备份

2. 物理备份

对于前者,常用的工具是MySQL自带的mysqldump,对于后者,常用的工具是Percona提供的XtraBackup。

对于规模比较小,业务并不繁忙的数据库,一般都是选择mysqldump。

那么,mysqldump的备份原理是什么呢?

抛开源码不谈,其实我们可以通过打开general log,查看mysqldump全库备份时执行的命令来了解mysqldump背后的原理。

打开general log

mysql> set global general_log=on;

其中,general log的存放路径可通过以下命令查看

mysql> show variables like '%general_log_file%';

执行全库备份

# mysqldump --master-data=2  -R --single-transaction -A -phello > 3306_20160518.sql

其中

--master-data指定为2指的是会在备份文件中生成CHANGE MASTER的注释。具体在本例中,指的是

-- CHANGE MASTER TO MASTER_LOG_FILE='mysql2-bin.000049', MASTER_LOG_POS=587;

如果该值设置为1,则生成的是CHANGE MASTER的命令,而不是注释。

-R 备份存储过程与函数

--single-transaction 获取InnoDB表的一致性备份。

-A 相当于--all-databases。

下面来看看general log中的内容

160518 11:00:59    14 Connect   root@localhost on
14 Query /*!40100 SET @@SQL_MODE='' */
14 Query /*!40103 SET TIME_ZONE='+00:00' */
14 Query FLUSH /*!40101 LOCAL */ TABLES
14 Query FLUSH TABLES WITH READ LOCK
14 Query SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ
14 Query START TRANSACTION /*!40100 WITH CONSISTENT SNAPSHOT */
14 Query SHOW VARIABLES LIKE 'gtid\_mode'
14 Query SHOW MASTER STATUS
14 Query UNLOCK TABLES
14 Query SELECT LOGFILE_GROUP_NAME, FILE_NAME, TOTAL_EXTENTS, INITIAL_SIZE, ENGINE, EXTRA FROM INFORMATION_SCHEMA.FILES WHERE FILE_TYPE = 'UNDO LOG' AND FILE_NAME IS NOT NULL GROUP BY LOGFILE_GROUP_NAME, FILE_NAME, ENGINE ORDER BY LOGFILE_GROUP_NAME
14 Query SELECT DISTINCT TABLESPACE_NAME, FILE_NAME, LOGFILE_GROUP_NAME, EXTENT_SIZE, INITIAL_SIZE, ENGINE FROM INFORMATION_SCHEMA.FILES WHERE FILE_TYPE = 'DATAFILE' ORDER BY TABLESPACE_NAME, LOGFILE_GROUP_NAME
14 Query SHOW DATABASES
14 Query SHOW VARIABLES LIKE 'ndbinfo\_version'

其中,比较重要的有以下几点:

1. FLUSH /*!40101 LOCAL */ TABLES

Closes all open tables, forces all tables in use to be closed, and flushes the query cache.

2. FLUSH TABLES WITH READ LOCK

执行flush tables操作,并加一个全局读锁,很多童鞋可能会好奇,这两个命令貌似是重复的,为什么不在第一次执行flush tables操作的时候加上锁了,其实,这样做的原因在于可以尽量减少加锁的影响。

加上全局读锁,只允许读,不允许更新操作。

3. SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ

设置当前会话的事务隔离等级为RR,RR可避免不可重复读和幻读。

4. START TRANSACTION /*!40100 WITH CONSISTENT SNAPSHOT */

获取当前数据库的快照,这个是由mysqldump中--single-transaction决定的。

这个只适用于支持事务的表,在MySQL中,只有Innodb。

注意:START TRANSACTION和START TRANSACTION WITH CONSISTENT SNAPSHOT并不一样,

START TRANSACTION WITH CONSISTENT SNAPSHOT是开启事务的一致性快照。

RC下的START TRANSACTION WITH CONSISTENT SNAPSHOT相当于RR下的START TRANSACTION。

不明白事务的童鞋可能觉得这点会比较绕,其实所谓的不可重复读和幻读可简单理解为,在同一个事务内,两次SELECT的结果并不相同。

之所以要使用START TRANSACTION WITH CONSISTENT SNAPSHOT,因为每个表的备份时间并不相同,这就要求在对第一张表进行备份的期间,对第二个表进行的操作,并不会反映到第二张表开始备份时执行的SELECT操作中。(注:mysqldump备份的底层实现即是select * from tab)。而这用START TRANSACTION就无法实现。

5.  SHOW MASTER STATUS

这个是由--master-data决定的,记录了开始备份时,binlog的状态信息,包括MASTER_LOG_FILE和MASTER_LOG_POS

6.  UNLOCK TABLES

释放锁。

因为我的数据库中只有以下四个库

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

备份的时候可以发现只备份了mysql和test,并没有备份information_schema和performance_schema。

下面来看看备份mysql和test的日志输出信息,

因日志输出信息太多,在这里,只选择test库的日志信息。test库中一共有两张表test和test1。

                   14 Init DB   test
14 Query SHOW CREATE DATABASE IF NOT EXISTS `test`
14 Query SAVEPOINT sp
14 Query show tables 14 Query show table status like 'test'
14 Query SET SQL_QUOTE_SHOW_CREATE=1
14 Query SET SESSION character_set_results = 'binary'
14 Query show create table `test`
14 Query SET SESSION character_set_results = 'utf8'
14 Query show fields from `test`
14 Query SELECT /*!40001 SQL_NO_CACHE */ * FROM `test`
14 Query SET SESSION character_set_results = 'binary' 14 Query use `test`
14 Query select @@collation_database
14 Query SHOW TRIGGERS LIKE 'test'
14 Query SET SESSION character_set_results = 'utf8'
14 Query ROLLBACK TO SAVEPOINT sp 14 Query show table status like 'test1'
14 Query SET SQL_QUOTE_SHOW_CREATE=1
14 Query SET SESSION character_set_results = 'binary'
14 Query show create table `test1`
14 Query SET SESSION character_set_results = 'utf8'
14 Query show fields from `test1`
14 Query SELECT /*!40001 SQL_NO_CACHE */ * FROM `test1`
14 Query SET SESSION character_set_results = 'binary' 14 Query use `test`
14 Query select @@collation_database
14 Query SHOW TRIGGERS LIKE 'test1'
14 Query SET SESSION character_set_results = 'utf8'
14 Query ROLLBACK TO SAVEPOINT sp 14 Query RELEASE SAVEPOINT sp 14 Query use `test`
14 Query select @@collation_database
14 Query SET SESSION character_set_results = 'binary'
14 Query SHOW FUNCTION STATUS WHERE Db = 'test'
14 Query SHOW CREATE FUNCTION `mycat_seq_currval`
14 Query SHOW PROCEDURE STATUS WHERE Db = 'test'
14 Query SET SESSION character_set_results = 'utf8'
14 Quit

从上述输出可以看出:

1. 备份的核心是SELECT /*!40001 SQL_NO_CACHE */ * FROM `test1`语句。

该语句会查询到表test1的所有数据,在备份文件中会生成相应的insert语句。

其中SQL_NO_CACHE的作用是查询的结果并不会缓存到查询缓存中。

2. SHOW CREATE DATABASE IF NOT EXISTS `test`,show create table `test1`

生成创库语句和创表语句。

3. SHOW TRIGGERS LIKE 'test1'

可以看出,如果不加-R参数,默认是会备份触发器的。

4. SHOW FUNCTION STATUS WHERE Db = 'test'

SHOW CREATE FUNCTION `mycat_seq_currval`

SHOW PROCEDURE STATUS WHERE Db = 'test'

用于备份存储过程和函数。

5. 设置SAVEPOINT,然后备份完每个表后再回滚到该SAVEPOINT。

不知道为什么要这么设置,感觉这样完全没必要,

因为前面通过START TRANSACTION WITH CONSISTENT SNAPSHOT开启的事务只能通过commit或者rollback来结束,而不是ROLLBACK TO SAVEPOINT sp。

PS:这样做不会阻塞在备份期间对已经备份表的ddl操作,具体可见下面的“后续补充”第三点。

总结:

1. mysqldump的本质是通过select * from tab来获取表的数据的。

2. START TRANSACTION /*!40100 WITH CONSISTENT SNAPSHOT */必须放到FLUSH TABLES WITH READ LOCK和UNLOCK TABLES之间,放到之前会造成START TRANSACTION /*!40100 WITH CONSISTENT SNAPSHOT */和FLUSH TABLES WITH READ LOCK之间执行的DML语句丢失,放到之后,会造成从库重复插入数据。

3. mysqldump只适合放到业务低峰期做,如果备份的过程中数据操作很频繁,会造成Undo表空间越来越大,undo表空间默认是放到共享表空间中的,而ibdata的特性是一旦增大,就不会收缩。

4. mysqldump的效率还是比较低下,START TRANSACTION /*!40100 WITH CONSISTENT SNAPSHOT */只能等到所有表备份完后才结束,其实效率比较高的做法是备份完一张表就提交一次,这样可尽快释放Undo表空间快照占用的空间。但这样做,就无法实现对所有表的一致性备份。

参考:

http://tencentdba.com/blog/mysqldump-backup-principle/

后续补充:

最近翻了下源码,msyqldump对应的是client/mysqldump.c。里面的注释还是有一定的参考意义,一并附上。

1. 关于FLUSH TABLE和FLUSH TABLES WITH READ LOCK的

  /*
We do first a FLUSH TABLES. If a long update is running, the FLUSH TABLES
will wait but will not stall the whole mysqld, and when the long update is
done the FLUSH TABLES WITH READ LOCK will start and succeed quickly. So,
FLUSH TABLES is to lower the probability of a stage where both mysqldump
and most client connections are stalled. Of course, if a second long
update starts between the two FLUSHes, we have that bad stall.
*/

2. 为什么备份结束时没有执行commit操作

  /*
No reason to explicitely COMMIT the transaction, neither to explicitely
UNLOCK TABLES: these will be automatically be done by the server when we
disconnect now. Saves some code here, some network trips, adds nothing to
server.
*/

3. 关于ROLLBACK TO SAVEPOINT的

/**
ROLLBACK TO SAVEPOINT in --single-transaction mode to release metadata
lock on table which was already dumped. This allows to avoid blocking
concurrent DDL on this table without sacrificing correctness, as we
won't access table second time and dumps created by --single-transaction
mode have validity point at the start of transaction anyway.
Note that this doesn't make --single-transaction mode with concurrent
DDL safe in general case. It just improves situation for people for whom
it might be working.
*/

上面的意思是不阻塞并发的DDL操作。

下面具体来测试一下:

第一种情况:

会话1发起事务,并查询test表的值,然后会话2进行添加列操作,该操作被hang住。

第二种情况:

会话1发起事务,然后会话2进行添加列操作,发现该操作成功。

第三种情况:

模仿mysqldump的备份原理,设置断点。

注意,DDL操作发起的时间是在执行了select * from test之后,如果是在之前,根据上面第二种情况的测试,是可以进行DDL操作的。

此时,如果不执行ROLLBACK TO SAVEPOINT sp,DDL操作会一直hang下去,执行了该操作后,DDL操作可以继续执行了。

由此可见,ROLLBACK TO SAVEPOINT确实可以提高DDL的并发性。

但还有一点需要注意,如果DDL操作是发生在select * from test之前,正如第二种情况所演示的,DDL操作会成功,此时,查看test表的数据会报以下错误:

root@test 04:32:49 > select * from test;
ERROR 1412 (HY000): Table definition has changed, please retry transaction

对应mysqldump,会报如下错误:

mysqldump: Error 1412: Table definition has changed, please retry transaction when dumping table `test` at row: 0

mysqldump备份7的更多相关文章

  1. 使用Mysqldump 备份数据库

    使用Mysqldump 备份数据库 1.备份一个数据库 mysqldump --user [user name] --password=[password] [database name] >  ...

  2. mysqldump备份原理6

    写在前面:我们在使用mysqldump备份数据时,请一定记住要加上 -q 参数,后果可能是很严重的,不要给自己挖坑哦.到底为什么呢,且听我慢慢道来! 先来看看 mysqldump –help 中,关于 ...

  3. mysqldump备份数据库时出现when using LOCK TABLES

    用mysqldump备份数据库时,如果出现when using LOCK TABLES,解决办法是加上 --skip-lock-tables 例如: 用mysqldump备份数据库时出现 29: Fi ...

  4. mysqldump备份原理

    现网中数据库运维时,要经常对数据库做热备.为保证恢复时数据的完整性与一致性, 一种方法是在备份之前锁表,但锁表会影响正在运行的业务. mysqldump是当前MySQL中最常用的备份工具,通过mysq ...

  5. mysqldump 备份数据说明+ 避免锁表

    1.mysqldump命令备份Mysql数据库的参数说明 在用mysqldump备份使用那些参数选项是最完美的组合呢?--skip-opt--create-option                 ...

  6. 如何使用mysqldump备份数据库

    一.背景 在开发项目中,数据库是核心资产.除了做主备冗余增加可靠性外,定期备份数据也是必须的. 使用mysqldump备份数据具有操作简单,备份和恢复时间短的优点(mysqldump备份数据生成的是批 ...

  7. crontab的mysqldump备份任务未能完全正确执行的故障处理

    crontab是每个运维一线人员必须掌握的技术,熟练运用crontab可以自动帮助我们执行重复性的工作,提高运维的工作效率.它就像一个闹钟,在特定的时间,准时响应并执行相应的任务.如果你的工作经常与L ...

  8. mysql8.0绿色版安装及mysqldump备份

    1.下载mysql绿色版压缩包https://dev.mysql.com/downloads/mysql/ 2.解压到安装目录后,在根目录创建data文件夹 3.把mysql下的bin目录添加到环境变 ...

  9. mysqldump备份表中有大字段失败的排错过程

    几天前收到某个业务项目,MySQL数据库逻辑备份mysqldump备份失败的邮件,本是在休假,但本着工作认真负责,7*24小时不间断运维的高尚职业情操,开始了DBA的排错之路(一开始数据库的备份都是成 ...

随机推荐

  1. tyvj1519博彩游戏

    博彩游戏 From admin 背景 Background Bob最近迷上了一个博彩游戏…… 描述 Description 这个游戏的规则是这样的:每花一块钱可以得到一个随机数R,花上N块钱就可以得到 ...

  2. 高性能PHP支持静态类型

    PHP+QB是一个可选的PHP虚拟机,它声称在性能上提供了数量级的提升.而负面影响就是它需要所有的内容都必须是静态类型,同时也对数组做了一些限制. 静态 类型声明 是通过PHPDoc语法的一个扩展添加 ...

  3. POJ 2391 Ombrophobic Bovines ★(Floyd+二分+拆点+最大流)

    [题意]有n块草地,一些奶牛在草地上吃草,草地间有m条路,一些草地上有避雨点,每个避雨点能容纳的奶牛是有限的,给出通过每条路的时间,问最少需要多少时间能让所有奶牛进入一个避雨点. 和POJ2112很类 ...

  4. C++学习笔记:List容器

    http://www.cplusplus.com/reference/list/list/ #include <list> list l:初始化一个0大小的表 list l(10):初始化 ...

  5. 自定义SharePoint列表新增、编辑、查看页面(NewForm、EditForm、DispForm)

    转:http://blog.csdn.net/lance_lot1/article/details/7966571 在项目中,用户需求涉及在一个列表录入项目信息,选择一个项目后,与该项目相关的信息实现 ...

  6. 如何在asp.net mvc3中使用HttpStatusCode

    下载了asp.net mvc 4的源码看了看,没怎么看清楚.不过个人觉得MVC4 beta中Web API这个是比较不错的,虽然说它是往传统回归. web api最好的莫过于它更加适合使用jquery ...

  7. 序列化类型为XX的对象时检测到循环引用

    /// 产品列表展示 /// </summary> /// <returns></returns> ) { //获得所有组别 Galasys_IBLL.IT_BIZ ...

  8. 错误 1 在应用程序级别之外使用注册为 allowDefinition='

    原文:错误 1 在应用程序级别之外使用注册为 allowDefinition='MachineToApplication' 的节是错误的,银流沙 昨天运行一个.NET网站项目时,出现了以下问题: 在应 ...

  9. 消息系统Kafka介绍

    1.  概述 Kafka是Linkedin于2010年12月份开源的消息系统,它主要用于处理活跃的流式数 据.活跃的流式数据在web网站应用中非常常见,这 些数据包括网站的pv.用户访问了什么内容,搜 ...

  10. 扩展类加载器-------改变JAVA的父优先类加载顺序

    java的类加载机制默认情况下是采用委托模型:当加载某个类时JVM会首先尝试用当前类加载器的父类加载器加载该类,若父类加载器加载不到再由当前类加载器来加载,因此这种模型又叫做“父优先”模型. 但是在实 ...