MySQL Backup mysqldump備份流程學習--轉發
目錄
正文
我們都知道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.
FLUSH TABLES WITH READ LOCK
語句獲取的是一個全域性讀鎖而不是進行鎖表,不像LOCK TABLES
和UNLOCK TABLES
語句的行為;- 只要任何表當前被
LOCK TABLES
鎖住時,執行UNLOCK TABLES
會隱式提交任何活動的事務,不過已執行FLUSH TABLES WITH READ LOCK
再執行UNLOCK TABLES
並不會進行提交,因為後續的語句並不會獲取表鎖; - 開始一個事務會造成
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
備份的主要流程:
- 一開始執行
FLUSH TABLES
關閉例項中所有的表; - 執行語句
FLUSH TABLES WITH READ LOCK
獲取全域性表的讀鎖,保證表一致性; - 設定會話級別事務的隔離級別為
REPEATABLE READ
,保證事務期間資料的一致性; - 執行語句
START TRANSACTION /*!40100 WITH CONSISTENT SNAPSHOT */
建立一個一致性事務快照; - 檢視是否開啟了GTID;
- 獲取當前狀態下的binlog檔案及位置資訊(如有指定選項 --master-data);
- 執行
UNLOCK TABLES
釋放全域性表讀鎖; - 開始備份第一個資料庫資料,為事務建立一個檢查點,備份完一張表之後還原至檢查點再接著備份下一張表,直至該資料庫所有的表備份完成,接著備份下一個資料庫資料,直至所有資料庫資料備份完成;
- 當備份完最後一個數據庫資料後釋放檢查點,退出並中止事務。
參考
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
☆〖本人水平有限,文中如有錯誤還請留言批評指正!〗☆