1. 本文转至:http://blog.csdn.net/cug_jiang126com/article/details/49824471

在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的状态

深入理解--single-transaction:

打开general_log,准备一个数据量较小的db,开启备份,添加--single-transaction和--master-data=2参数,查看general_log,信息如下,每一步添加了我的理解

整个dump过程是同一个连接id 32,这样能保证在设置session级别的变量的时候不影响到其他连接
thread_id: 32
 argument: ucloudbackup@localhost on 
*************************** 14. row ***************************
thread_id: 32
 argument: /*!40100 SET @@SQL_MODE='' */
*************************** 15. row ***************************
thread_id: 32
 argument: /*!40103 SET TIME_ZONE='+00:00' */
*************************** 16. row ***************************
thread_id: 32
 argument: FLUSH /*!40101 LOCAL */ TABLES
*************************** 17. row ***************************
thread_id: 32
 argument: FLUSH TABLES WITH READ LOCK
批注:因为开启了--master-data=2,这时就需要flush tables with read lock锁住全库,记录当时的master_log_file和master_log_pos点
*************************** 18. row ***************************
thread_id: 32
 argument: SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ
批注:--single-transaction参数的作用,设置事务的隔离级别为可重复读,即REPEATABLE READ,这样能保证在一个事务中所有相同的查询读取到同样的数据,也就大概保证了在dump期间,如果其他innodb引擎的线程修改了表的数据并提交,对该dump线程的数据并无影响,然而这个还不够,还需要看下一条
*************************** 19. row ***************************
thread_id: 32
 argument: START TRANSACTION /*!40100 WITH CONSISTENT SNAPSHOT */
这时开启一个事务,并且设置WITH CONSISTENT SNAPSHOT为快照级别(如果mysql版本高于某一个版本值,我还不大清楚40100代表什么版本)。想象一下,如果只是可重复读,那么在事务开始时还没dump数据时,这时其他线程修改并提交了数据,那么这时第一次查询得到的结果是其他线程提交后的结果,而WITH CONSISTENT SNAPSHOT能够保证在事务开启的时候,第一次查询的结果就是事务开始时的数据A,即使这时其他线程将其数据修改为B,查的结果依然是A,具体的测试看我下面的测试结果
*************************** 20. row ***************************
thread_id: 32
 argument: SHOW MASTER STATUS
这时候执行这个命令来记录当时的master_log_file和master_log_pos点,注意为什么这个时候记录,而不是再18 row和19 row之间就记录,个人认为应该都是可以的,这里是测试结果,start  transaction并不会产生binlog的移动,而18 row和19 row的动作也在同一个thread id中
mysql> show master status;
+------------------+----------+--------------+------------------+
| File             | Position | Binlog_Do_DB | Binlog_Ignore_DB |
+------------------+----------+--------------+------------------+
| mysql-bin.000003 |     1690 |              |                  |
+------------------+----------+--------------+------------------+
1 row in set (0.00 sec)

mysql> START TRANSACTION /*!40100 WITH CONSISTENT SNAPSHOT */;
Query OK, 0 rows affected (0.00 sec)

mysql> show master status;
+------------------+----------+--------------+------------------+
| File             | Position | Binlog_Do_DB | Binlog_Ignore_DB |
+------------------+----------+--------------+------------------+
| mysql-bin.000003 |     1690 |              |                  |
+------------------+----------+--------------+------------------+
1 row in set (0.00 sec)

*************************** 21. row ***************************
thread_id: 32
 argument: UNLOCK TABLES
等记录完成后,就立即释放了,因为现在已经在一个事务中了,其他线程再修改数据已经无所谓,在本线程中已经是可重复读,这也是这一步必须在19 rows之后的原因,如果20 rows和21 rows都在19 rows之前的话就不行了,因为这时事务还没开启,一旦释放,其他线程立即就可以更改数据,从而无法保证得到事务开启时最准确的pos点。

*************************** 22. row ***************************
thread_id: 32
 argument: 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 IN (SELECT DISTINCT LOGFILE_GROUP_NAME FROM INFORMATION_SCHEMA.FILES WHERE FILE_TYPE = 'DATAFILE' AND TABLESPACE_NAME IN (SELECT DISTINCT TABLESPACE_NAME FROM INFORMATION_SCHEMA.PARTITIONS WHERE TABLE_SCHEMA='mysql' AND TABLE_NAME IN ('user'))) GROUP BY LOGFILE_GROUP_NAME, FILE_NAME, ENGINE ORDER BY LOGFILE_GROUP_NAME
*************************** 23. row ***************************
thread_id: 32
 argument: SELECT DISTINCT TABLESPACE_NAME, FILE_NAME, LOGFILE_GROUP_NAME, EXTENT_SIZE, INITIAL_SIZE, ENGINE FROM INFORMATION_SCHEMA.FILES WHERE FILE_TYPE = 'DATAFILE' AND TABLESPACE_NAME IN (SELECT DISTINCT TABLESPACE_NAME FROM INFORMATION_SCHEMA.PARTITIONS WHERE TABLE_SCHEMA='mysql' AND TABLE_NAME IN ('user')) ORDER BY TABLESPACE_NAME, LOGFILE_GROUP_NAME
*************************** 24. row ***************************
thread_id: 32
 argument: mysql
*************************** 25. row ***************************
thread_id: 32
 argument: SHOW TABLES LIKE 'user'
*************************** 26. row ***************************
thread_id: 32
 argument: show table status like 'user'
 
dump表以前都需要show一下各自信息,确保表,视图等不损坏,可用,每一步错了mysqldump都会报错并中断,给出对应的错误码,常见的myqldump错误请参考我的另外一篇blog http://blog.csdn.net/cug_jiang126com/article/details/49359699
 
*************************** 27. row ***************************
thread_id: 32
 argument: SET OPTION SQL_QUOTE_SHOW_CREATE=1
*************************** 28. row ***************************
thread_id: 32
 argument: SET SESSION character_set_results = 'binary'
*************************** 29. row ***************************
thread_id: 32
 argument: show create table `user`
*************************** 30. row ***************************
thread_id: 32
 argument: SET SESSION character_set_results = 'utf8'
*************************** 31. row ***************************
thread_id: 32
 argument: show fields from `user`
*************************** 32. row ***************************
thread_id: 32
 argument: SELECT /*!40001 SQL_NO_CACHE */ * FROM `user`
这就是我们show processlist时看到的信息,而数据是怎么通过一条select语句就dump到本地文件里的呢,并且还转成成相应的create和insert语句,这就是mysqldump这个客户端工具的工作了,这里不做讨论
*************************** 33. row ***************************
最后并没有看到commit,因为在整个事务中,其实并没有修改任何数据,只是为了保证可重复读得到备份时间点一致性的快照,dump完成后提交不提交应该无所谓了。

myisam引擎为什么无法保证在--single-transaction下得到一致性的备份?

因为它压根就不支持事务,自然就无法实现上述的过程,虽然添加了--single-transaction参数的myisam表处理过程和上面的完全一致,但是因为不支持事务,在整个dump过程中无法保证可重复读,无法得到一致性的备份。而innodb在备份过程中,虽然其他线程也在写数据,但是dump出来的数据能保证是备份开始时那个binlog pos的数据。

myisam引擎要保证得到一致性的数据的话,他是如何实现的呢?

它是通过添加--lock-all-tables,这样在flush tables with read lock后,直到整个dump过程结束,断开线程后才会unlock tables释放锁(没必要主动发unlock tables指令),整个dump过程其他线程不可写,从而保证数据的一致性

如果我一定要在mysiam引擎中也添加--single-transaction参数,再用这个备份去创建从库或恢复到指定时间点,会有什么样的影响?

我个人的理解是如果整个dump过程中只有简单的insert操作,是没有关系的,期间肯定会有很多的主键重复错误,直接跳过或忽略就好了。如果是update操作,那就要出问题了,分几种情况考虑

1) 如果是基于时间点的恢复,假设整个dump过程有update a  set id=5 where id=4之类的操作,相当于重复执行两次该操作,应该问题不大
2) 如果是创建从库,遇到上面的sql从库会报错,找不到该记录,这时跳过就好
3)不管是恢复还是创建从库,如果dump过程中有update a set id=id+5 之类的操作,那就有问题,重复执行两次,数据全变了。

深入理解--lock-all-tables

打开general_log,准备一个数据量较小的db,开启备份,添加--lock-all-tables(其实也是默认设置)和--master-data=2参数,查看general_log,信息如下,理解--lock-all-tables怎么保证数据一致性

mysql> select thread_id,argument from general_log  where thread_id=185\G
*************************** 1. row ***************************
thread_id: 185
 argument: ucloudbackup@10.10.108.15 on 
*************************** 2. row ***************************
thread_id: 185
 argument: /*!40100 SET @@SQL_MODE='' */
*************************** 3. row ***************************
thread_id: 185
 argument: /*!40103 SET TIME_ZONE='+00:00' */
*************************** 4. row ***************************
thread_id: 185
 argument: FLUSH /*!40101 LOCAL */ TABLES
*************************** 5. row ***************************
thread_id: 185
 argument: FLUSH TABLES WITH READ LOCK

这里flush tables with read lock之后就不会主动unlock tables,保证整个dump过程整个db数据不可更改,也没有事务的概念了
*************************** 6. row ***************************
thread_id: 185
 argument: SHOW MASTER STATUS
同样记录主库的位置
*************************** 7. row ***************************
thread_id: 185
 argument: 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
*************************** 8. row ***************************
thread_id: 185
 argument: 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
*************************** 9. row ***************************
thread_id: 185
 argument: SHOW DATABASES
*************************** 10. row ***************************
thread_id: 185
 argument: jjj
*************************** 11. row ***************************
thread_id: 185
 argument: SHOW CREATE DATABASE IF NOT EXISTS `jjj`

测试可重复读和快照读(WITH CONSISTENT SNAPSHOT )

准备工作3.1(测试可重读)

session 1:
mysql> select * from xx;
+------+
| id   |
+------+
|    1 |
|    2 |
|    3 |
|    4 |
+------+
mysql> SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ;
Query OK, 0 rows affected (0.00 sec)
设置事务隔离级别为可重复读

mysql> START TRANSACTION ;
Query OK, 0 rows affected (0.00 sec)
我们先不开快照读观察现象

session 2:
mysql> insert into xx values (5);
Query OK, 1 row affected (0.00 sec)

session 1:
mysql> select * from xx;
+------+
| id   |
+------+
|    1 |
|    2 |
|    3 |
|    4 |
|    5 |
+------+
5 rows in set (0.00 sec)
批注:这时因为没有设置快照读,所以当session 2有数据更新时,可查到该数据,接

下来我们继续在session 2 插入数据
session 2:
mysql> insert into xx values (6);
Query OK, 1 row affected (0.00 sec)

这时再观察session 1的数据
session 1
mysql> select * from xx;
+------+
| id   |
+------+
|    1 |
|    2 |
|    3 |
|    4 |
|    5 |
+------+
5 rows in set (0.00 sec)
查询发现还是只有5条,表示可重复实现了。

准备工作3.2(测试快照读)

session 1
mysql> select * from xx;
+------+
| id   |
+------+
|    1 |
+------+
1 row in set (0.00 sec)
mysql> SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ;
Query OK, 0 rows affected (0.00 sec)
mysql> START TRANSACTION /*!40100 WITH CONSISTENT SNAPSHOT */;
Query OK, 0 rows affected (0.00 sec)

这时我们在session 2插入数据
session 2:
mysql> insert into xx values (2);
Query OK, 1 row affected (0.00 sec)

这时我们再观察session 1的结果
session 1:
mysql> select * from xx;
+------+
| id   |
+------+
|    1 |
+------+
1 row in set (0.00 sec)
发现还是只有一条数据,证明实现了快照读
mysql> commit;
Query OK, 0 rows affected (0.00 sec)
mysql> select * from xx;
+------+
| id   |
+------+
|    1 |
|    2 |
+------+
2 rows in set (0.00 sec)
事务1 提交后方可看见第二条记录

 
 

[转]深入理解mysqldump原理 --single-transaction --lock-all-tables --master-data的更多相关文章

  1. [转]深入理解mysqldump原理

    本文转至:http://blog.csdn.net/cug_jiang126com/article/details/49824471 在mysqldump过程中,之前其实一直不是很理解为什么加了--s ...

  2. 《深入理解mybatis原理》 MyBatis事务管理机制

    MyBatis作为Java语言的数据库框架,对数据库的事务管理是其很重要的一个方面.本文将讲述MyBatis的事务管理的实现机制. 首先介绍MyBatis的事务Transaction的接口设计以及其不 ...

  3. node.js学习(三)简单的node程序&&模块简单使用&&commonJS规范&&深入理解模块原理

    一.一个简单的node程序 1.新建一个txt文件 2.修改后缀 修改之后会弹出这个,点击"是" 3.运行test.js 源文件 使用node.js运行之后的. 如果该路径下没有该 ...

  4. Atitit 图像处理 深刻理解梯度原理计算.v1 qc8

    Atitit 图像处理 深刻理解梯度原理计算.v1 qc8 1.1. 图像处理  梯度计算  基本梯度 内部梯度 外部梯度 方向梯度1 2. 图像梯度就是图像边缘吗?2 1.1. 图像处理  梯度计算 ...

  5. 深入理解PHP原理之变量作用域

    26 Aug 08 深入理解PHP原理之变量作用域(Scope in PHP)   作者: Laruence(   ) 本文地址: http://www.laruence.com/2008/08/26 ...

  6. 深入理解PHP原理之变量分离/引用

    19 Sep 08 深入理解PHP原理之变量分离/引用(Variables Separation) 作者: Laruence(   ) 本文地址: http://www.laruence.com/20 ...

  7. 《深入理解mybatis原理》 Mybatis初始化机制具体解释

    对于不论什么框架而言.在使用前都要进行一系列的初始化,MyBatis也不例外. 本章将通过下面几点具体介绍MyBatis的初始化过程. 1.MyBatis的初始化做了什么 2. MyBatis基于XM ...

  8. 《深入理解mybatis原理》 MyBatis的架构设计以及实例分析

    作者博客:http://blog.csdn.net/u010349169/article/category/2309433 MyBatis是目前非常流行的ORM框架,它的功能很强大,然而其实现却比较简 ...

  9. 轻松理解Redux原理及工作流程

    轻松理解Redux原理及工作流程 Redux由Dan Abramov在2015年创建的科技术语.是受2014年Facebook的Flux架构以及函数式编程语言Elm启发.很快,Redux因其简单易学体 ...

随机推荐

  1. JS中数组Array的用法

    js数组元素的添加和删除一直比较迷惑,今天终于找到详细说明的资料了. var arr = new Array();  // 初始化数组arr[0] = "aaa";arr[1] = ...

  2. 剑指Offer:面试题24——二叉搜索树的后序遍历序列(java实现)

    问题描述: 输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历的结果.如果是则返回true,否则返回false.假设输入的数组的任意两个数字都互不相同. 思路: 1.首先后序遍历的结果是[(左子 ...

  3. C#中的 正则表达式

    String 类包括许多字符串搜索和替换方法,当你要在较大字符串中定位文本字符串时,可以使用这些方法. 当你希望在较大字符串中定位若干子字符串之一时,或者当你希望在字符串中标识模式时,正则表达式最有用 ...

  4. ant安装(linux)

    1.下载 下载地址:http://ant.apache.org/bindownload.cgi 下载apache-ant-1.9.7-bin.tar.gz(当前最新版本),将该下载包拷贝到/data/ ...

  5. Timus Online Judge 1001. Reverse Root

    Input The input stream contains a set of integer numbers Ai (0 ≤ Ai ≤ 1018). The numbers are separat ...

  6. iptables转发

    需求 将流入服务器的公网IP的80端口的流量全部转发到另一个公网IP(1.2.3.4)的80端口上. 操作 iptables -P FORWARD ACCEPT iptables -t nat -A ...

  7. linux网络完全与防护

    7.1 网络封包联机进入主机的流程   7.1.1 封包进入主机的流程 1.经过防火墙的分析 iptables 主要功能是封包过滤 主要分析TCP/IP的封包表头来进行过滤的机制 分析的是OSI的第二 ...

  8. 问题Initial SessionFactory creation failed.org.hibernate.HibernateException: /hibernate.cfg.xml not found解决方法

    问题Initial SessionFactory creation failed.org.hibernate.HibernateException: /hibernate.cfg.xml not fo ...

  9. markdown 的基本操作

    文档 http://mux.alimama.com/posts/620?spm=0.0.0.0.4VVnvp http://www.jianshu.com/p/1e402922ee32/ MdChar ...

  10. 循序渐进之Spring AOP(5) - 创建切面

    在掌握了可用的增强后,接下来要做的就是精确的描述切点.前面的示例都是指定一个目标类并把增强织入到所有方法中,实际开发显然会有更精细的筛选需求,比如对所有类中名称以test结尾的方法加入监控执行时间,或 ...