您的位置:首页 > 数据库 > MySQL

Mysqldump原理

2016-05-25 19:20 411 查看
mysqldump的原理:

mysqldump是当前MySQL中最常用的备份工具,mysqldump产生的备份,最终是要结合binlog进行恢复。mysqldump也可以准确得到binlog的恢复点。

那么mysqldump中如何保证数据一致性并生成备份的呢?下面通过一个常用示例来解释mysqldump的原理。(仅针对InnoDB存储引擎举例)

创建测试库、表,并插入数据

mysql -uroot -poracle -S/tmp/mysql.sock -e'create database test_bak;'

mysql -uroot -poracle -S/tmp/mysql.sock -e'create table test_bak.test (id int);'

mysql -uroot -poracle -S/tmp/mysql.sock -e'insert into test_bak.test values(1),(2),(3),(4),(5);'

mysql -uroot -poracle -S/tmp/mysql.sock -e'select * from test_bak.test;'

+------+

| id |

+------+

| 1 |

| 2 |

| 3 |

| 4 |

| 5 |

+------+

开启general.log:

mysql> show global variables like "%genera%";

+------------------+---------------------------+

| Variable_name | Value |

+------------------+---------------------------+

| general_log | OFF |

| general_log_file | /mysql/data/localhost.log |

+------------------+---------------------------+

2 rows in set (0.00 sec)

mysql> set global general_log=on;

Query OK, 0 rows affected (0.02 sec)

mysql> show global variables like "%genera%";

+------------------+---------------------------+

| Variable_name | Value |

+------------------+---------------------------+

| general_log | ON |

| general_log_file | /mysql/data/localhost.log |

+------------------+---------------------------+

2 rows in set (0.01 sec)

mysqldump导出test_bak的数据:

/usr/local/mysql/bin/mysqldump -uroot -poracle -R --single-transaction --master-data=2 -S/tmp/mysql.sock -B test_bak > /mysql/backup/bak.sql

查看/mysql/data/localhost.log:

160525 20:54:14 13 Connect root@localhost on

13 Query /*!40100 SET @@SQL_MODE='' */

13 Query /*!40103 SET TIME_ZONE='+00:00' */

13 Query FLUSH /*!40101 LOCAL */ TABLES

13 Query FLUSH TABLES WITH READ LOCK

13 Query SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ

13 Query START TRANSACTION /*!40100 WITH CONSISTENT SNAPSHOT */

13 Query SHOW VARIABLES LIKE 'gtid\_mode'

13 Query SHOW MASTER STATUS

13 Query UNLOCK TABLES

13 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 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 IN ('test_bak'))) GROUP BY LOGFILE_GROUP_NAME, FILE_NAME, ENGINE ORDER BY LOGFILE_GROUP_NAME

13 Query 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 IN ('test_bak')) ORDER BY TABLESPACE_NAME, LOGFILE_GROUP_NAME

13 Query SHOW VARIABLES LIKE 'ndbinfo\_version'

13 Init DB test_bak

13 Query SHOW CREATE DATABASE IF NOT EXISTS `test_bak`

13 Query SAVEPOINT sp

13 Query show tables

13 Query show table status like 'test'

13 Query SET SQL_QUOTE_SHOW_CREATE=1

13 Query SET SESSION character_set_results = 'binary'

13 Query show create table `test`

13 Query SET SESSION character_set_results = 'utf8'

13 Query show fields from `test`

13 Query SELECT /*!40001 SQL_NO_CACHE */ * FROM `test`

13 Query SET SESSION character_set_results = 'binary'

13 Query use `test_bak`

13 Query select @@collation_database

13 Query SHOW TRIGGERS LIKE 'test'

13 Query SET SESSION character_set_results = 'utf8'

13 Query ROLLBACK TO SAVEPOINT sp

13 Query RELEASE SAVEPOINT sp

13 Query use `test_bak`

13 Query select @@collation_database

13 Query SET SESSION character_set_results = 'binary'

13 Query SHOW FUNCTION STATUS WHERE Db = 'test_bak'

13 Query SHOW PROCEDURE STATUS WHERE Db = 'test_bak'

13 Query SET SESSION character_set_results = 'utf8'

13 Quit

第一行,执行connect是通过mysqldump选项中的-u, -p, -S来进行端口、用户验证,然后连接服务器。

其中的flush tables 、flush tables with read lock、 unlock tables及其中的show master status是响应选项--master-data.

通过一个瞬间的锁表,利用show master status来得到binlog的位置。在backup.sql中,可以找到类似下面的信息。

-- CHANGE MASTER TO MASTER_LOG_FILE='mysql-bin.000003', MASTER_LOG_POS=2154;

进行瞬间的锁表就是要保证得到正确的binlog位置。flush tables后,当前数据库快照就是我们要备份的,

通过show master status得到binlog位置信息。那么如何保证对当前数据库快照进行备份呢?

结合选项--single-transaction,mysqldump的处理是start transaction。由于INNODB的MVCC机制,

start transacion会产生一个事务id,利用这个事务id可以过滤该事务之后的事务对数据库的更新操作,

从而得到当前快照的备份。

有个细节要注意,flush tables ;flush tables with read lock; 为什么不直接就加上read lock,这样写的好处是什么?

其实这样做可以尽可能少的减少加锁的影响,减少冲突。

另一个细节要注意是start transaction要放在flush tables 与 unlock tables之间,不能放在前面或者后面。

flush tables后,当前数据库快照就是我们要备份的,然后show master status也得到了binlog位置信息。

而start transaction是通过begin一个事务来获取这个快照的,如果放在前面或者后面,会造成数据丢失或者数据的重复插入。

另外,还有很多general log信息,来得到当前快照中的数据库、表、存储过程及数据等。下面仅以test库中一个t1表的部分内容为例说明。

SHOW CREATE DATABASE IF NOT EXISTS `test_bak`; 服务器响应该语句得到test_bak库的创建语句

SHOW CREATE DATABASE IF NOT EXISTS `test_bak` 加上if not exists保证在create时不存在test_bak库才创建test_bak。

show tables 获取test库中所有的表。

show table status like ‘test’ 得到test表的状态信息,便于进一步处理。

show create table `test` 生成test表的创建语句。

SELECT /*!40001 SQL_NO_CACHE */ * FROM `test` 该语句得到表t1的所有数据,在backup.sql中会生成相应的insert语句,

恢复时执行这些数据的insert操作。其中sql_no_cache的作用是避免查询结果缓存(不是不在缓存中查询结果)。

在general log中还可以看到一系列mysqldump处理后发送到服务器的语句,然后mysqldump利用服务器返回的结果进行处理,

从而得到备份文件bak.sql

参考文档:
http://tencentdba.com/blog/mysqldump-backup-principle/
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: