程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 數據庫知識 >> MYSQL數據庫 >> MySQL綜合教程 >> mysqldump的實現原理,mysqldump實現原理

mysqldump的實現原理,mysqldump實現原理

編輯:MySQL綜合教程

mysqldump的實現原理,mysqldump實現原理


對於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相當於在執行完START TRANSACTION後對每個Innodb表執行了SELECT操作。

   不明白事務的童鞋可能覺得這點會比較繞,其實所謂的不可重復讀和幻讀可簡單理解為,在同一個事務內,兩次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。

 

總結:

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/

 

    

  

 

    

   

    

 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved