我们都知道MySQL逻辑备份工具mysqldump可以保证备份数据的一致性,但是它是怎么保持一致性的?

本文不讨论mysqldump具体的选项和用法,一直对mysqldump的工作机制梳理的不太清楚,这篇主要来分析下mysqldump的工作原理和工作步骤,了解它为什么可以获取一致性的备份。

关于mysqldump常用选项说明与用法参考另一篇博文:MySQL Backup mysqldump 常用选项与主要用法

通过打开general log的方法来记录mysqldump备份的过程。

前期准备

开启general log

(root@localhost) [(none)] > set global general_log = 1;
Query OK, 0 rows affected (0.00 sec) (root@localhost) [(none)] > show global variables like '%general%';
+------------------+---------------------------------+
| Variable_name | Value |
+------------------+---------------------------------+
| general_log | ON |
| general_log_file | /data/mysql/3306/data/dbabd.log |
+------------------+---------------------------------+
2 rows in set (0.01 sec)

mysqldump执行全库备份

# mysqldump -uadmin -p -h192.168.58.3 -P3306 -E -R --triggers --single-transaction --master-data=2 -A > test_all.sql

分析general log日志

开头部分

53 Connect   admin@dbabd on  using TCP/IP
53 Query /*!40100 SET @@SQL_MODE='' */
53 Query /*!40103 SET TIME_ZONE='+00:00' */
53 Query FLUSH /*!40101 LOCAL */ TABLES
53 Query FLUSH TABLES WITH READ LOCK
53 Query SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ
53 Query START TRANSACTION /*!40100 WITH CONSISTENT SNAPSHOT */
53 Query SHOW VARIABLES LIKE 'gtid\_mode'
53 Query SHOW MASTER STATUS
53 Query UNLOCK TABLES
53 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 AND LOGFILE_GROUP_NAME IS NOT NULL GROUP BY LOGFILE_GROUP_NAME, FILE_NAME, ENGINE, TOTAL_EXTENTS, INITIAL_SIZE ORDER BY LOGFILE_GROUP_NAME
53 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
53 Query SHOW DATABASES
53 Query SHOW VARIABLES LIKE 'ndbinfo\_version'
  • 备份连接,设置sql_mode为'',设置time_zone
53 Connect   admin@dbabd on  using TCP/IP
53 Query /*!40100 SET @@SQL_MODE='' */
53 Query /*!40103 SET TIME_ZONE='+00:00' */
  • FLUSH TABLES
53 Query     FLUSH /*!40101 LOCAL */ TABLES

关闭所有的表,并强制关闭所有正在使用的表,同时也会移除所有query cache结果。

详细说明可以参考官方文档:FLUSH TABLES

根据官文文档的描述:

FLUSH TABLES is not permitted when there is an active LOCK TABLES ... READ. To flush and lock tables, use FLUSH TABLES tbl_name ... WITH READ LOCK instead.

意思是如果有一个会话正在执行LOCK TABLES ... READ语句,另一个会话执行FLUSH TABLES语句是不允许的,会被阻塞。可以使用FLUSH TABLES ... WITH READ LOCK替代。

  • FLUSH TABLES WITH READ LOCK
53 Query     FLUSH TABLES WITH READ LOCK

关闭所有打开的表并且对所有数据库表加一个全局读锁。

详细说明可以参考官方文档:FLUSH TABLES WITH READ LOCK

根据官方文档的描述

FLUSH TABLES WITH READ LOCK acquires a global read lock rather than

table locks, so it is not subject to the same behavior as LOCK TABLES

and UNLOCK TABLES with respect to table locking and implicit commits:

UNLOCK TABLES implicitly commits any active transaction only if any

tables currently have been locked with LOCK TABLES. The commit does

not occur for UNLOCK TABLES following FLUSH TABLES WITH READ LOCK

because the latter statement does not acquire table locks.

Beginning a transaction causes table locks acquired with LOCK TABLES

to be released, as though you had executed UNLOCK TABLES. Beginning a

transaction does not release a global read lock acquired with FLUSH

TABLES WITH READ LOCK.

  1. FLUSH TABLES WITH READ LOCK语句获取的是一个全局读锁而不是进行锁表,不像LOCK TABLES和UNLOCK TABLES语句的行为;
  2. 只要任何表当前被LOCK TABLES锁住时,执行UNLOCK TABLES会隐式提交任何活动的事务,不过已执行FLUSH TABLES WITH READ LOCK再执行UNLOCK TABLES并不会进行提交,因为后续的语句并不会获取表锁;
  3. 开始一个事务会造成LOCK TABLES获得的表锁释放,就像已经执行了UNLOCK TABLES。开始一个事务并不会造成FLUSH TABLES WITH READ LOCK获取的全局读锁释放。
  • 设置会话隔离级别为REPEATABLE READ
53 Query     SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ
  • 开启一致性快照事务
53 Query     START TRANSACTION /*!40100 WITH CONSISTENT SNAPSHOT */

因为要开启一致性快照事务,所以必须将务事务的隔离级别设置成REPEATABLE READ。所以便有了上面设置会话级隔离级别的语句。

A consistent read means that InnoDB uses multi-versioning to present to a query a snapshot of the database at a point in time. The query sees the changes made by transactions that committed before that point of time, and no changes made by later or uncommitted transactions.

根据官方文档的描述,这一步是为了确保该事务开启时之后读取的快照都是基于同一个时刻的,同时获取得到一个事务号,就是SELECT都能读取到一开始同一个的READ VIEW,不受之后其他事务修改或者未提交事务的影响。

详细说明可参考官方文档:innodb-consistent-read

  • 查看是否开启GTID模式
53 Query     SHOW VARIABLES LIKE 'gtid\_mode'
  • 获取当前binlog的位置信息
53 Query     SHOW MASTER STATUS
  • 释放全局读锁
53 Query     UNLOCK TABLES
  • 查看所有数据库信息
53 Query     SHOW DATABASES

备份部分

来看下开始备份表的日志,这里选取test1为例说明:

53 Init DB   mysql
53 Query SHOW CREATE DATABASE IF NOT EXISTS `mysql`
53 Query SAVEPOINT sp
53 Query show tables
53 Query show table status like 'columns\_priv'
53 Query SET SQL_QUOTE_SHOW_CREATE=1
53 Query SET SESSION character_set_results = 'binary'
53 Query show create table `columns_priv`
53 Query SET SESSION character_set_results = 'utf8'
53 Query show fields from `columns_priv`
53 Query show fields from `columns_priv`
53 Query SELECT /*!40001 SQL_NO_CACHE */ * FROM `columns_priv`
53 Query SET SESSION character_set_results = 'binary'
53 Query use `mysql`
53 Query select @@collation_database
53 Query SHOW TRIGGERS LIKE 'columns\_priv'
53 Query SET SESSION character_set_results = 'utf8'
53 Query ROLLBACK TO SAVEPOINT sp
…………省略………… 53 Init DB test1
53 Query SHOW CREATE DATABASE IF NOT EXISTS `test1`
53 Query SAVEPOINT sp
53 Query show tables
53 Query show table status like 't1'
53 Query SET SQL_QUOTE_SHOW_CREATE=1
53 Query SET SESSION character_set_results = 'binary'
53 Query show create table `t1`
53 Query SET SESSION character_set_results = 'utf8'
53 Query show fields from `t1`
53 Query show fields from `t1`
53 Query SELECT /*!40001 SQL_NO_CACHE */ * FROM `t1`
53 Query SET SESSION character_set_results = 'binary'
53 Query use `test1`
53 Query select @@collation_database
53 Query SHOW TRIGGERS LIKE 't1'
53 Query SET SESSION character_set_results = 'utf8'
53 Query ROLLBACK TO SAVEPOINT sp
53 Query show events
53 Query use `test1`
53 Query select @@collation_database
53 Query SET SESSION character_set_results = 'binary'
53 Query SHOW FUNCTION STATUS WHERE Db = 'test1'
53 Query SHOW PROCEDURE STATUS WHERE Db = 'test1'
…………省略………… 53 Init DB test2
53 Query SHOW CREATE DATABASE IF NOT EXISTS `test2`
53 Query SAVEPOINT sp
53 Query show tables
53 Query show table status like 't1'
53 Query SET SQL_QUOTE_SHOW_CREATE=1
53 Query SET SESSION character_set_results = 'binary'
53 Query show create table `t1`
53 Query SET SESSION character_set_results = 'utf8'
53 Query show fields from `t1`
53 Query show fields from `t1`
53 Query SELECT /*!40001 SQL_NO_CACHE */ * FROM `t1`
53 Query SET SESSION character_set_results = 'binary'
53 Query use `test2`
53 Query select @@collation_database
53 Query SHOW TRIGGERS LIKE 't1'
53 Query SET SESSION character_set_results = 'utf8'
53 Query ROLLBACK TO SAVEPOINT sp
53 Query RELEASE SAVEPOINT sp
53 Query show events
53 Query use `test2`
53 Query select @@collation_database
53 Query SET SESSION character_set_results = 'binary'
53 Query SHOW FUNCTION STATUS WHERE Db = 'test2'
53 Query SHOW PROCEDURE STATUS WHERE Db = 'test2'
53 Query SET SESSION character_set_results = 'utf8'
53 Quit
  • 查看建库语句,所有数据库进行循环顺序备份
53 Init DB   test1
53 Query SHOW CREATE DATABASE IF NOT EXISTS `test1`
  • 创建检查点
53 Query     SAVEPOINT sp

创建一个检查点,检查点的作用是在一个事务中执行ROLLBACK TO SAVEPOINT语句之后能够将事务回滚到检查点位置而不中止事务。

详细说明可参考官方文档:SAVEPOINT

mysqldump备份是通过执行SELECT进行的,但是SELECT语句执行没结束同时会持有该对象的MDL锁,为了保证在备份期间不影响已经备份表的DDL操作被阻塞,所以就有了SAVEPOINT,每次备份完一张表就将事务回滚到SAVEPOINT的位置,同时这个操作会释放该表的MDL锁,但这并不会中止这个事务,其他事务可以对这张表进行DDL操作。

  • 获取表的状态信息
53 Query     show table status like 'columns\_priv'
  • 设置字符集为binary
53 Query     SET SESSION character_set_results = 'binary'

mysqldump为了更好的备份表结构,将字符集先设置成binary,避免出错。

  • 备份建表语句
53 Query     show tables
53 Query show table status like 't1'
  • 设置字符集为utf8
53 Query     SET SESSION character_set_results = 'utf8'

开始备份表数据时将字符集设置为数据库的字符集。

  • 获取表的字段信息
53 Query     show fields from `t1`
  • 开始备份表
53 Query     SELECT /*!40001 SQL_NO_CACHE */ * FROM `t1`
  • 开始备份触发器
53 Query     SHOW TRIGGERS LIKE 't1'
  • 回滚到检查点
53 Query     ROLLBACK TO SAVEPOINT sp

以上一张表就算备份完成,接下去就是循环上面步骤备份完该数据库下所有的表。

完成所有表的备份之后,最后备份的数据库中的事件、函数、存储过程:

53 Query     show events
53 Query use `test1`
53 Query select @@collation_database
53 Query SET SESSION character_set_results = 'binary'
53 Query SHOW FUNCTION STATUS WHERE Db = 'test1'
53 Query SHOW PROCEDURE STATUS WHERE Db = 'test1'

至此,一个数据库的备份完成,开始备份其他数据库。

结尾部分

来看下结尾部分的日志

53 Query     ROLLBACK TO SAVEPOINT sp
53 Query RELEASE SAVEPOINT sp

当备份完最后一个数据库的最后一张表后释放了检查点,再完成最后一个数据库事件、函数和存储过程的备份之后进行退出,退出默认会进行提交操作,所有备份结束。

总结

通过以上的日志分析,可以总结下mysqldump备份的主要流程:

  1. 一开始执行FLUSH TABLES关闭实例中所有的表;
  2. 执行语句FLUSH TABLES WITH READ LOCK获取全局表的读锁,保证表一致性;
  3. 设置会话级别事务的隔离级别为REPEATABLE READ,保证事务期间数据的一致性;
  4. 执行语句START TRANSACTION /*!40100 WITH CONSISTENT SNAPSHOT */创建一个一致性事务快照;
  5. 查看是否开启了GTID
  6. 获取当前状态下的binlog文件及位置信息(如有指定选项 --master-data);
  7. 执行UNLOCK TABLES释放全局表读锁;
  8. 开始备份第一个数据库数据,为事务创建一个检查点,备份完一张表之后还原至检查点再接着备份下一张表,直至该数据库所有的表备份完成,接着备份下一个数据库数据,直至所有数据库数据备份完成;
  9. 当备份完最后一个数据库数据后释放检查点,退出并中止事务。

参考

https://dev.mysql.com/doc/refman/5.7/en/mysqldump.html

https://dev.mysql.com/doc/refman/5.7/en/flush.html

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

http://www.unixfbi.com/475.html

☆〖本人水平有限,文中如有错误还请留言批评指正!〗☆

MySQL Backup mysqldump备份流程学习的更多相关文章

  1. MySQL 的mysqldump备份

    MySQL 的mysqldump备份 来自<mysql技术内幕 innodb存储引擎> --single-transaction:只对innodb表有效 --lock-tables:对My ...

  2. MySQL使用mysqldump备份及还原

    MySQL可以使用mysqldump进行数据的逻辑备份,配合开启bin log日志可以实现数据的全量恢复及增量恢复 MySQL版本查看 修改配置文件记录bin log日志 [mysqld] #bin ...

  3. MySQL Backup mysqldump 常用选项与主要用法

    The mysqldump client utility performs logical backups, producing a set of SQL statements that can be ...

  4. MySQL 基于mysqldump备份工具实战演练

    前言: 细节提示:先执行 show global variables like 'log_bin';看看log_bin的值,如果服务器变量log_bin的值为OFF,需要修改my.cnf配置文件,将l ...

  5. mysql之 mysqldump 备份恢复详解

    mysqldump是MySQL用于转存储数据库的客户端程序.转储包含创建表和/或装载表的SQL语句 ,用来实现轻量级的快速迁移或恢复数据库,是mysql数据库实现逻辑备份的一种方式. mysqldum ...

  6. mysql之mysqldump——备份与还原

    导出数据库里的某一张表 [root@localhost ~]# mysqldump -uroot -p test bptest>fi.mysql #导出test数据库中的bptest表 Ente ...

  7. MySQL Backup myloader

    之前的博文当中提到备份工具mydumper的使用,而软件包中还包含了与之对应的恢复工具myloader,本文就总结下myloader的用法.关于mydumper的安装与使用可以参考之前的博文:MySQ ...

  8. mysql备份与还原-mysqldump备份、mysql与source还原

    以下都以在linux操作系统上的mysql为例 mysqldump备份 mysqldump实际就是将数据库中的数据转化为建库.建表和插入记录的sql语句 1.备份一个数据库 [或其中几个表],不指定表 ...

  9. mysql数据库数据备份还原

    1.直接在命令行里面执行 备份一个数据库:mysqldump -h server -u username -p password db_name > database-sqlbkp_`date ...

随机推荐

  1. 【资料下载区】【GMT43相关代码、资料下载地址】更新日期2017/06/28

    [GMT43相关文档][更新中...] GMT43原理图(PDF)下载GMT43说明书(PDF)下载GMT43机械结构尺寸(PDF)下载 [GMT43相关例程代码][ARM][更新中...] 基于HA ...

  2. Direct3D 11 Tutorial 5: 3D Transformation_Direct3D 11 教程5:3D转型

    概述 在上一个教程中,我们从模型空间到屏幕渲染了一个立方体. 在本教程中,我们将扩展转换的概念并演示可以通过这些转换实现的简单动画. 本教程的结果将是围绕另一个轨道运行的对象. 展示转换以及如何将它们 ...

  3. Gephi学习笔记

    使用gephi对图数据进行可视化操作,下面网址是gephi的说明文档 https://seinecle.github.io/gephi-tutorials/generated-pdf/semantic ...

  4. 【物联网】国内几大云计算厂商的物联网IOT解决方案-阿里云、腾讯、百度、华为、青云(转)

    一.前言随着万物互联时代的来临,IOT逐渐成为各大云计算厂商重点发力的方向,作为平台厂商,提供的是包含接入.存储.管理.计算.展示等多个方面的综合能力,我这里就根据它们各自的特点和能力,简单介绍下它们 ...

  5. 判断当前的Activity的是否处于栈顶

    lockAppName 是需要判断Activity的全称(包括包名). private boolean getTopApp(Context mContext) { String lockAppName ...

  6. 禅道docker化(Centos7.2)

    操作步骤 确认服务器禅道版本及容器禅道版本 服务器禅道版本:9.6.2 容器禅道版本:9.6.3 版本sql比对 下载官方9.6.3源码包url:http://dl.cnezsoft.com/zent ...

  7. C#串口小助手

    做技术的通病,什么都想学,什么都想亲手做一遍.不然总感觉心里不踏实. 考研期间,利用晚上一点时间,照葫芦画瓢,练习使用c#快速开发一个简单的串口小助手. 这种前后端分离的设计方法,大大提高了开发速度, ...

  8. B - Assignment

    Tom owns a company and he is the boss. There are n staffs which are numbered from 1 to n in this com ...

  9. codechef cook 103 div2

    第一次打codechef...不太会用这oj. A: #include <bits/stdc++.h> #define mk(a,b) make_pair(a,b) #define pii ...

  10. Java课程课后作业02之动手动脑

    一.编写一个方法,使用以上算法生成指定数目(比如1000个)的随机整数 数学算法原理: 可以使用的方法:Math中的random类以及random类,区别:Math中的random类只能用于生成随机数 ...