本文转至: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原理的更多相关文章

  1. [转]深入理解mysqldump原理 --single-transaction --lock-all-tables --master-data

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

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

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

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

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

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

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

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

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

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

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

  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. 音频 PCM 数据的采集和播放

    PCM(Pulse Code Modulation)脉冲编码调制 —— 音频的采集与量化过程. PCM数据是最原始的音频数据完全无损,所以PCM数据虽然音质优秀但体积庞大. 为了解决这个问题先后诞生了 ...

  2. Python爬虫项目--爬取某宝男装信息

    本次爬取用到的知识点有: 1. selenium 2. pymysql 3  pyquery 正文 1. 分析目标网站 1. 打开某宝首页, 输入"男装"后点击"搜索&q ...

  3. mysql备份数据库出错mysqldump: [ERROR] unknown option '--no-beep'

    公司数据库前一版本是部署在windows上面的,由于业务需要,迁移到linux,之前一段脚本在windows下使用定时任务执行正常. mysqldump -uzzz -pxxxx --opt --de ...

  4. 22.Mysql磁盘I/O

    22.磁盘I/O问题磁盘IO是数据库性能瓶颈,一般优化是通过减少或延缓磁盘读写来减轻磁盘IO的压力及其对性能的影响.增强磁盘读写性能和吞吐量也是重要的优化手段. 22.1 使用磁盘阵列 RAID(Re ...

  5. Oracle_PL/SQL(10) 定时器job

    定时器job1.定义 定时器指在特定的时间执行特定的操作. 可以多次执行.说明:特定的操作:指一个完成特定功能的存储过程.多次执行:指可以每分钟.每小时.每天.每周.每月.每季度.每年等周期性的运行. ...

  6. Linux CentOS 7 下 Apache Tomcat 7 安装与配置

    前言 记录一下Linux CentOS 7安装Tomcat7的完整步骤. 下载 首先需要下载tomcat7的安装文件,地址如下: http://mirror.bit.edu.cn/apache/tom ...

  7. 关于call_rcu在内核模块退出时可能引起kernel panic的问题

    http://paulmck.livejournal.com/7314.html RCU的作者,paul在他的blog中有提到这个问题,也明确提到需要在module exit的地方使用rcu_barr ...

  8. Array Division 808D

    D. Array Division time limit per test 2 seconds memory limit per test 256 megabytes input standard i ...

  9. java mina框架使用

    1.目前为止,看到写mina最清晰的一篇博客:https://my.oschina.net/ielts0909/blog/85946! 2.官网的开发文档:http://mina.apache.org ...

  10. NC 5系自定义显示公式

    1.继承NcInnerFunction(nc.vo.pub.formulaset.function.NcInnerFunction) 在方法中引用父类方法function,并在里面写方法 @Overr ...