Ⅰ、mysqldump的簡單使用與注意點
1.1 基本參數
只備份innodb,用不了幾個參數,記住下面幾個即可,其他的沒什么卵用
-A 備份所有的database
-B 備份哪幾個數據庫
-R 備份存儲過程(-- routines)
-E 備份定時任務(-- events)
-d 只備份表結構
-w 備份過濾數據
-t 只備份數據
-q 直接讀數據,繞過緩沖池,默認已加
--triggers 備份觸發器
--master-data=2 在備份文件中以注釋的形式記錄備份開始時binlog的position,默認值是1,不注釋
tips:
①--set-gtid-purged=OFF 如果實例開了gtid最好加上這個參數,不然備份時候會報warning,且備份出來的數據恢復到其他版本的實例上會報錯:A partial dump from a server that has GTIDs is not allowed.
②--dump-slave,該參數可以用作在從庫做備份獲取主庫的位置點,來做一個新從庫,避免在主庫做備份影響業務,帶該參數備份時,從上sql線程會被kill,備份完再拉起
常見用法:
mysqldump --single-transaction -B test a > backup.sql 備份test庫和a庫
mysqldump --single-transaction test a > backup.sql 備份test庫下的a表
mysqldump --single-transaction test a -w "c=12"> backup.sql
1.2 其他參數
--lock-tables(-l)
在備份中依次鎖住所有表,一般用於myisam備份,備份時數據庫只能提供讀操作,以此來保證數據一致性,該參數和--single-transaction是互斥的,所以實例中既存在myisam又存在innodb則,只能使用該參數
--lock-all-tables(-x)
比上面的參數力度更大,備份時將整個實例鎖住
1.3 重點
--single-transaction
必須加(一個事務中導出數據,確保產生一致性的備份數據)
my.cnf中配上下面配置
[mysqldump]
single-transaction
master-data=2
Ⅱ、mysqldump實現原理剖析
2.1 開glog嗖哈一把看看嘛(__)
session 1:
(root@localhost) [(none)]> truncate mysql.general_log;
Query OK, 0 rows affected (0.02 sec)
(root@localhost) [(none)]> set global general_log = 1;
Query OK, 0 rows affected (0.00 sec)
(root@localhost) [(none)]> set global log_output = 'table';
Query OK, 0 rows affected (0.00 sec)
session 2:
[root@VM_0_5_centos src]# mysqldump --single-transaction --master-data=2 -B dump_test > /tmp/back.sql
session 1:
(root@localhost) [(none)]> set global general_log = 0;
Query OK, 0 rows affected (0.00 sec)
(root@localhost) [(none)]> set global log_output = 'file';
Query OK, 0 rows affected (0.00 sec)
(root@localhost) [(none)]> select thread_id,left(argument,64) from mysql.general_log;
(root@localhost) [(none)]> select argument from mysql.general_log where thread_id=239 order by event_time;
FLUSH /*!40101 LOCAL */ TABLES
# 先把表刷一把,減少ftwrl鎖的等待時間
FLUSH TABLES WITH READ LOCK
# 把當前整個實例鎖成只讀
SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ
# 設置備份線程事務隔離級別為rr
START TRANSACTION /*!40100 WITH CONSISTENT SNAPSHOT */
# 開啟事務
SHOW VARIABLES LIKE 'gtid\_mode'
SHOW MASTER STATUS
# 獲得當前二進制日志位置
UNLOCK TABLES
# 釋放實例級別的只讀鎖
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 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 ('dump_test'))) GROUP BY LOGFILE_GROUP_NAME, FILE_NAME, ENGINE, TOTAL_EXTENTS, INITIAL_SIZE ORDER BY LOGFILE_GROUP_NAME
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 ('dump_test')) ORDER BY TABLESPACE_NAME, LOGFILE_GROUP_NAME
SHOW VARIABLES LIKE 'ndbinfo\_version'
dump_test
SHOW CREATE DATABASE IF NOT EXISTS `dump_test`
SAVEPOINT sp
# 使用savepoint sp,便於回滾,用於快速釋放metadata數據共享鎖
show tables
show table status like 'dump\_inno'
SET SQL_QUOTE_SHOW_CREATE=1
SET SESSION character_set_results = 'binary'
show create table `dump_inno`
SET SESSION character_set_results = 'utf8'
show fields from `dump_inno`
show fields from `dump_inno`
SELECT /*!40001 SQL_NO_CACHE */ * FROM `dump_inno`
SET SESSION character_set_results = 'binary'
use `dump_test`
select @@collation_database
SHOW TRIGGERS LIKE 'dump\_inno'
SET SESSION character_set_results = 'utf8'
# 以上部分備份數據
ROLLBACK TO SAVEPOINT sp
RELEASE SAVEPOINT sp
# 回到savepoint sp,釋放metadata的鎖
# 每取一張表的數據,就rollback to savepoint sp(一個savepoint就夠了)
root@localhost on using Socket
/*!40100 SET @@SQL_MODE='' */
/*!40103 SET TIME_ZONE='+00:00' */
2.2 mysqldump流程小結
- | 操作 | 解析 |
---|---|---|
step1 | flush tables/flush tables with read lock | 將實例鎖成只讀 |
step2 | SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ/START TRANSACTION | 開啟rr隔離級別的事務 |
step3 | SHOW MASTER STATUS/UNLOCK TABLES | 獲取二進制日志位置並釋放全局讀鎖 |
step4 | SAVEPOINT sp | 設置回滾點 |
step5 | select xxx | 備份數據 |
step6 | ROLLBACK TO SAVEPOINT sp/RELEASE SAVEPOINT sp | 結束一張表備份,回到sp |
2.3 關鍵點細說
- start transaction with consistent snapshot
位置點問題:事務隔離級別是rr,開始事務,並且馬上創建一個read_view,所以mysqldump備份的數據是備份開始時候的數據而不是備份結束時的數據(備份了30min,整個過程實例一直可讀可寫,備份的是30min之前的數據而不是30min之后的數據)
執行start transaction同時(而不是等到執行第一條sql)建立與本事務一致性讀的snapshot
- --single-transaction
所有的數據都是在一個事務里面讀出來,而且事務隔離級別是如rr的,所以讀到的數據是一致的
一致性備份:整個備份從start transaction開始,備份所有的表,所有的表的數據都是在一個事務里面,通過select導出來
- savepoint保存點(4.1還是5.0加進來的)
savepoint很少用,真正用的最多就是備份的時候,一張表備份完,會回滾到對應保存點,此時對應備份的表上面的元數據鎖都釋放,這時候可以這個表可以做ddl操作。
否則在一個事務里,持有元數據鎖,要做ddl(比如其他線程想對這里一個表創建索引),即使備份完了也做不了,要等所有備份結束才能動
沒有savepoint時,只讀鎖要持有整個事務時間,而不是表備份的時間
Ⅲ、常規操作
①備份並且壓縮
mysqldump --single-transaction --master-data=1 --triggers -R -E -B sbtest | pv | gzip -c > sbtest.backup.tgz
壓縮過的備份恢復
gunzip < sbtest.backup.tgz | mysql
②備份並且壓縮到遠程服務器
mysqldump --single-transaction --master-data=1 --triggers -R -E -B sbtest | gzip -c | ssh root@test-3 'cat > /tmp/sbtest.sql.gz'
備份校驗,另行考慮
③備份文件使用
mysql < xxx.sql;
tips:
備份占用帶寬很大,需要調度算法確保同一個集群中同時只有一個機器做備份,或者不每天做備份從而錯開備份時間