關于mysqldump,這個參數(shù)你可能還不知道
在前面文章中,有提到過 mysqldump 備份文件中記錄的時間戳數(shù)據(jù)都是以 UTC 時區(qū)為基礎的,在篩選恢復單庫或單表時要注意時區(qū)差別。后來再次查看文檔,發(fā)現(xiàn) tz-utc、skip-tz-utc 參數(shù)與此有關,本篇文章我們一起來看下此參數(shù)的作用吧。
? ?1.tz-utc與skip-tz-utc參數(shù)介紹
這兩個參數(shù)可以作用于 mysqldump 備份過程中,互為相反參數(shù)。顧名思義可以看出,一個參數(shù)是將時間戳改為 UTC 時區(qū),另一個是跳過時區(qū)變動。
在 mysql 服務器上執(zhí)行 mysqldump --help 的命令,可以看到下面一段話。
[root@host?~]#?mysqldump?--help
mysqldump??Ver?10.13?Distrib?5.7.23,?for?Linux?(x86_64)
Copyright?(c)?2000,?2018,?Oracle?and/or?its?affiliates.?All?rights?reserved.
...省略很多內(nèi)容
??--tz-utc????????????SET?TIME_ZONE='+00:00'?at?top?of?dump?to?allow?dumping?of
??????????????????????TIMESTAMP?data?when?a?server?has?data?in?different?time
??????????????????????zones?or?data?is?being?moved?between?servers?with
??????????????????????different?time?zones.
??????????????????????(Defaults?to?on;?use?--skip-tz-utc?to?disable.)--tz-utc 參數(shù)是 mysqldump 的默認參數(shù),會使得 mysqldump 的導出文件的頂部加上一個設置時區(qū)的語句 SET TIME_ZONE='+00:00' ,這個時區(qū)是格林威治時間,也就是0時區(qū)。這樣當導出 timestamp 時間戳字段時,會把在服務器設置的當前時區(qū)下顯示的 timestamp 時間值轉化為在格林威治時間下顯示的時間。比如我們數(shù)據(jù)庫采用北京時間東八區(qū),mysqldump 導出的文件當中顯示的 timestamp 時間值相對于通過數(shù)據(jù)庫查詢顯示的時間倒退了8個小時。
知道了 --tz-utc ,那么 --skip-tz-utc 的含義就是當 mysqldump 導出數(shù)據(jù)時,不使用格林威治時間,而使用當前 mysql 服務器的時區(qū)進行導出,這樣導出的數(shù)據(jù)中顯示的 timestamp 時間值也和表中查詢出來的時間值相同。
? ?2.實驗參數(shù)具體作用
為了更清楚了解這對參數(shù)的作用,下面我們來具體測試下,我們知道 mysqldump 后可以跟 where 條件來備份部分數(shù)據(jù),若根據(jù) timestamp 字段來備份部分數(shù)據(jù),這對參數(shù)是否有影響呢?我們一并來驗證下:
先來看下我的環(huán)境設置及測試數(shù)據(jù):
mysql>?select?version();
+------------+
|?version()??|
+------------+
|?5.7.23-log?|
+------------+
1?row?in?set?(0.00?sec)
#?時區(qū)采用北京時間東八區(qū)
mysql>?show?variables?like?'time_zone';?
+---------------+--------+
|?Variable_name?|?Value??|
+---------------+--------+
|?time_zone?????|?+08:00?|
+---------------+--------+
1?row?in?set?(0.00?sec)
#?測試表?有datetime字段和timestamp字段?共10條數(shù)據(jù)?兩個時間顯示是相同的
mysql>?show?create?table?test_tb\G
***************************?1.?row?***************************
???????Table:?test_tb
Create?Table:?CREATE?TABLE?`test_tb`?(
??`increment_id`?int(11)?NOT?NULL?AUTO_INCREMENT?COMMENT?'自增主鍵',
??`stu_id`?int(11)?NOT?NULL?COMMENT?'學號',
??`stu_name`?varchar(20)?DEFAULT?NULL?COMMENT?'學生姓名',
??`dt_time`?datetime?NOT?NULL,
??`create_time`?timestamp?NOT?NULL?DEFAULT?CURRENT_TIMESTAMP?COMMENT?'創(chuàng)建時間',
??PRIMARY?KEY?(`increment_id`)
)?ENGINE=InnoDB?AUTO_INCREMENT=11?DEFAULT?CHARSET=utf8?COMMENT='測試表'
1?row?in?set?(0.00?sec)
mysql>?select?*?from?test_tb;
+--------------+--------+----------+---------------------+---------------------+
|?increment_id?|?stu_id?|?stu_name?|?dt_time?????????????|?create_time?????????|
+--------------+--------+----------+---------------------+---------------------+
|????????????1?|???1001?|?fgds?????|?2020-07-10?09:43:28?|?2020-07-10?09:43:28?|
|????????????2?|???1002?|?fgsw?????|?2020-10-10?09:43:28?|?2020-10-10?09:43:28?|
|????????????3?|???1003?|?vffg?????|?2020-10-10?02:00:00?|?2020-10-10?02:00:00?|
|????????????4?|???1004?|?wdsd?????|?2020-10-31?23:43:28?|?2020-10-31?23:43:28?|
|????????????5?|???1005?|?grdb?????|?2020-11-01?00:00:00?|?2020-11-01?00:00:00?|
|????????????6?|???1006?|?sdfv?????|?2020-11-01?02:00:00?|?2020-11-01?02:00:00?|
|????????????7?|???1007?|?fgfg?????|?2020-11-06?02:00:00?|?2020-11-06?02:00:00?|
|????????????8?|???1008?|?tyth?????|?2020-11-10?09:43:28?|?2020-11-10?09:43:28?|
|????????????9?|???1009?|?ewer?????|?2020-11-10?09:43:28?|?2020-11-10?09:43:28?|
|???????????10?|???1010?|?erre?????|?2020-11-11?15:17:03?|?2020-11-11?15:17:03?|
+--------------+--------+----------+---------------------+---------------------+mysqldump 默認開啟 tz-utc ,先來看下默認情況下的備份結果:
#?為更明顯看出結果?我們使用skip-extended-insert來一行行展現(xiàn)數(shù)據(jù)
#?全庫備份
[root@host?~]#?mysqldump?-uroot?-pxxxx??--skip-extended-insert?--databases?testdb?>?utc_testdb.sql
mysqldump:?[Warning]?Using?a?password?on?the?command?line?interface?can?be?insecure.
[root@host?~]#?more?utc_testdb.sql?
--?MySQL?dump?10.13??Distrib?5.7.23,?for?Linux?(x86_64)
--
--?Host:?localhost????Database:?testdb
--?------------------------------------------------------
--?Server?version???????5.7.23-log
...省略
/*!40103?SET?@OLD_TIME_ZONE=@@TIME_ZONE?*/;
/*!40103?SET?TIME_ZONE='+00:00'?*/;
#?先保存老時區(qū)?然后將此會話時區(qū)改為0時區(qū)
...省略
--
--?Dumping?data?for?table?`test_tb`
--
LOCK?TABLES?`test_tb`?WRITE;
/*!40000?ALTER?TABLE?`test_tb`?DISABLE?KEYS?*/;
INSERT?INTO?`test_tb`?VALUES?(1,1001,'fgds','2020-07-10?09:43:28','2020-07-10?01:43:28');
INSERT?INTO?`test_tb`?VALUES?(2,1002,'fgsw','2020-10-10?09:43:28','2020-10-10?01:43:28');
INSERT?INTO?`test_tb`?VALUES?(3,1003,'vffg','2020-10-10?02:00:00','2020-10-09?18:00:00');
INSERT?INTO?`test_tb`?VALUES?(4,1004,'wdsd','2020-10-31?23:43:28','2020-10-31?15:43:28');
INSERT?INTO?`test_tb`?VALUES?(5,1005,'grdb','2020-11-01?00:00:00','2020-10-31?16:00:00');
INSERT?INTO?`test_tb`?VALUES?(6,1006,'sdfv','2020-11-01?02:00:00','2020-10-31?18:00:00');
INSERT?INTO?`test_tb`?VALUES?(7,1007,'fgfg','2020-11-06?02:00:00','2020-11-05?18:00:00');
INSERT?INTO?`test_tb`?VALUES?(8,1008,'tyth','2020-11-10?09:43:28','2020-11-10?01:43:28');
INSERT?INTO?`test_tb`?VALUES?(9,1009,'ewer','2020-11-10?09:43:28','2020-11-10?01:43:28');
INSERT?INTO?`test_tb`?VALUES?(10,1010,'erre','2020-11-11?15:17:03','2020-11-11?07:17:03');
#?可以看出timestamp時間值減去了8小時?而datetime時間值不變
UNLOCK?TABLES;
/*!40103?SET?TIME_ZONE=@OLD_TIME_ZONE?*/;
#?再將時區(qū)改為原時區(qū)
/*!40101?SET?SQL_MODE=@OLD_SQL_MODE?*/;
--?Dump?completed?on?2020-11-11?15:34:21
#?使用where條件備份單表部分數(shù)據(jù)?備份11月份以來的數(shù)據(jù)
#?數(shù)據(jù)庫中查詢
mysql>?select?*?from?test_tb?where?create_time?>=?'2020-11-01?00:00:00';
+--------------+--------+----------+---------------------+---------------------+
|?increment_id?|?stu_id?|?stu_name?|?dt_time?????????????|?create_time?????????|
+--------------+--------+----------+---------------------+---------------------+
|????????????5?|???1005?|?grdb?????|?2020-11-01?00:00:00?|?2020-11-01?00:00:00?|
|????????????6?|???1006?|?sdfv?????|?2020-11-01?02:00:00?|?2020-11-01?02:00:00?|
|????????????7?|???1007?|?fgfg?????|?2020-11-06?02:00:00?|?2020-11-06?02:00:00?|
|????????????8?|???1008?|?tyth?????|?2020-11-10?09:43:28?|?2020-11-10?09:43:28?|
|????????????9?|???1009?|?ewer?????|?2020-11-10?09:43:28?|?2020-11-10?09:43:28?|
|???????????10?|???1010?|?erre?????|?2020-11-11?15:17:03?|?2020-11-11?15:17:03?|
+--------------+--------+----------+---------------------+---------------------+
6?rows?in?set?(0.00?sec)
#?mysqldump導出
[root@host?~]#?mysqldump?-uroot?-pxxxx??--skip-extended-insert?testdb?test_tb?--where?"create_time?>=?'2020-11-01?00:00:00'?"?>?utc_testdb2.sql
mysqldump:?[Warning]?Using?a?password?on?the?command?line?interface?can?be?insecure.
[root@host?~]#?more?utc_testdb2.sql?
--?MySQL?dump?10.13??Distrib?5.7.23,?for?Linux?(x86_64)
--
--?Host:?localhost????Database:?testdb
--?------------------------------------------------------
--?Server?version???????5.7.23-log
...
/*!40103?SET?@OLD_TIME_ZONE=@@TIME_ZONE?*/;
/*!40103?SET?TIME_ZONE='+00:00'?*/;
...省略
--
--?Dumping?data?for?table?`test_tb`
--
--?WHERE:??create_time?>=?'2020-11-01?00:00:00'?
LOCK?TABLES?`test_tb`?WRITE;
/*!40000?ALTER?TABLE?`test_tb`?DISABLE?KEYS?*/;
INSERT?INTO?`test_tb`?VALUES?(7,1007,'fgfg','2020-11-06?02:00:00','2020-11-05?18:00:00');
INSERT?INTO?`test_tb`?VALUES?(8,1008,'tyth','2020-11-10?09:43:28','2020-11-10?01:43:28');
INSERT?INTO?`test_tb`?VALUES?(9,1009,'ewer','2020-11-10?09:43:28','2020-11-10?01:43:28');
INSERT?INTO?`test_tb`?VALUES?(10,1010,'erre','2020-11-11?15:17:03','2020-11-11?07:17:03');
#?發(fā)現(xiàn)只導出4條
UNLOCK?TABLES;
/*!40103?SET?TIME_ZONE=@OLD_TIME_ZONE?*/;
--?Dump?completed?on?2020-11-11?15:58:56建議各位仔細看下上面導出結果,說實話,筆者原來也沒做過詳細測試,現(xiàn)在看到結果也是稍微有點吃驚的。默認情況下,全備出來的數(shù)據(jù)是沒問題的,雖然將 timestamp 時間值轉為0時區(qū)顯示,但當你導入數(shù)據(jù)庫時還會以你的數(shù)據(jù)庫時區(qū)來展示 timestamp 時間。但使用 where 條件導出部分數(shù)據(jù)時,卻出現(xiàn)了數(shù)據(jù)庫中查詢得出的結果與dump導出的結果不同的情況,這個時候 mysqldump 只導出了轉化成0時區(qū)后的時間值符合 where 條件的數(shù)據(jù),與直接查詢出的結果有出入,這是我原來沒注意到的。
再來看下使用 --skip-tz-utc 參數(shù),看下這個參數(shù)是否符合我們的預期:
#?使用skip-tz-utc全備
[root@host?~]#?mysqldump?-uroot?-pxxxx??--skip-extended-insert?--skip-tz-utc?--databases?testdb?>?skiputc_testdb.sql
mysqldump:?[Warning]?Using?a?password?on?the?command?line?interface?can?be?insecure.
[root@host?~]#?more?skiputc_testdb.sql?
--?MySQL?dump?10.13??Distrib?5.7.23,?for?Linux?(x86_64)
--
--?Host:?localhost????Database:?testdb
--?------------------------------------------------------
--?Server?version???????5.7.23-log
..省略?未見時區(qū)更改語句
--
--?Dumping?data?for?table?`test_tb`
--
LOCK?TABLES?`test_tb`?WRITE;
/*!40000?ALTER?TABLE?`test_tb`?DISABLE?KEYS?*/;
INSERT?INTO?`test_tb`?VALUES?(1,1001,'fgds','2020-07-10?09:43:28','2020-07-10?09:43:28');
INSERT?INTO?`test_tb`?VALUES?(2,1002,'fgsw','2020-10-10?09:43:28','2020-10-10?09:43:28');
INSERT?INTO?`test_tb`?VALUES?(3,1003,'vffg','2020-10-10?02:00:00','2020-10-10?02:00:00');
INSERT?INTO?`test_tb`?VALUES?(4,1004,'wdsd','2020-10-31?23:43:28','2020-10-31?23:43:28');
INSERT?INTO?`test_tb`?VALUES?(5,1005,'grdb','2020-11-01?00:00:00','2020-11-01?00:00:00');
INSERT?INTO?`test_tb`?VALUES?(6,1006,'sdfv','2020-11-01?02:00:00','2020-11-01?02:00:00');
INSERT?INTO?`test_tb`?VALUES?(7,1007,'fgfg','2020-11-06?02:00:00','2020-11-06?02:00:00');
INSERT?INTO?`test_tb`?VALUES?(8,1008,'tyth','2020-11-10?09:43:28','2020-11-10?09:43:28');
INSERT?INTO?`test_tb`?VALUES?(9,1009,'ewer','2020-11-10?09:43:28','2020-11-10?09:43:28');
INSERT?INTO?`test_tb`?VALUES?(10,1010,'erre','2020-11-11?15:17:03','2020-11-11?15:17:03');
#?timestamp時間值顯示與datetime顯示一樣?未做轉換
UNLOCK?TABLES;
--?Dump?completed?on?2020-11-11?16:23:32
#?使用skip-tz-utc備份部分數(shù)據(jù)
[root@host?~]#?mysqldump?-uroot?-pxxxx??--skip-extended-insert?--skip-tz-utc?testdb?test_tb?--where?"create_time?>=?'2020-11-01?00:00:00'?"?>?skiputc_testdb2.sql
mysqldump:?[Warning]?Using?a?password?on?the?command?line?interface?can?be?insecure.
[root@host?~]#?more?skiputc_testdb2.sql?
--?MySQL?dump?10.13??Distrib?5.7.23,?for?Linux?(x86_64)
--
--?Host:?localhost????Database:?testdb
--?------------------------------------------------------
--?Server?version???????5.7.23-log
..?省略
--
--?Dumping?data?for?table?`test_tb`
--
--?WHERE:??create_time?>=?'2020-11-01?00:00:00'?
LOCK?TABLES?`test_tb`?WRITE;
/*!40000?ALTER?TABLE?`test_tb`?DISABLE?KEYS?*/;
INSERT?INTO?`test_tb`?VALUES?(5,1005,'grdb','2020-11-01?00:00:00','2020-11-01?00:00:00');
INSERT?INTO?`test_tb`?VALUES?(6,1006,'sdfv','2020-11-01?02:00:00','2020-11-01?02:00:00');
INSERT?INTO?`test_tb`?VALUES?(7,1007,'fgfg','2020-11-06?02:00:00','2020-11-06?02:00:00');
INSERT?INTO?`test_tb`?VALUES?(8,1008,'tyth','2020-11-10?09:43:28','2020-11-10?09:43:28');
INSERT?INTO?`test_tb`?VALUES?(9,1009,'ewer','2020-11-10?09:43:28','2020-11-10?09:43:28');
INSERT?INTO?`test_tb`?VALUES?(10,1010,'erre','2020-11-11?15:17:03','2020-11-11?15:17:03');
#?6條數(shù)據(jù)?和數(shù)據(jù)庫中查詢一致
UNLOCK?TABLES;
--?Dump?completed?on?2020-11-11?16:28:39從上面結果可以看出,使用 --skip-tz-utc 參數(shù)后,timestamp 時間戳字段值不會轉換,導出部分數(shù)據(jù)也符合預期。
? ?3.一些小建議
那么這個參數(shù)的意義何在呢?當你的數(shù)據(jù)庫服務器處于不同時區(qū)時。假設一個服務器在北京(東八區(qū)),一個服務器在東京(東九區(qū)),現(xiàn)在需要將北京服務器里的數(shù)據(jù)導入至東京服務器。當導入按照默認不加 --skip-tz-utc 參數(shù)的dump文件,查詢的 timestamp 時間數(shù)據(jù)相對于在之前的東八區(qū)服務器的時間值多了一個小時,但由于東八區(qū)服務器里的13點和東九區(qū)服務器里的14點代表的是同一時刻,所以,在東九區(qū)的服務器里顯示的多出的一個小時,這樣顯示是正確的。而如果增加 --skip-tz-utc 參數(shù),dump文件導入東九區(qū)服務器后,盡管顯示的時間值和之前東八區(qū)服務器顯示的時間值相同,但兩者代表的時刻卻已經(jīng)不同。
關于這個參數(shù)應該如何使用,我們首先應該明白,是否加上 --skip-tz-utc 參數(shù),只會影響 timestamp 字段的導入導出,對 datetime 時間字段不會影響。
這里筆者建議首先對 timestamp 字段使用作出規(guī)范。比如 timestamp 字段只用于創(chuàng)建時間和更新時間需求,只代表該行數(shù)據(jù)的創(chuàng)建及更新時間,做到與業(yè)務弱相關,其他時間字段盡量使用 datetime 。這樣即使 mysqldump 采用不同參數(shù),實際產(chǎn)生影響也不大。
如果你的服務器處于不同時區(qū),那建議還是按照默認來,這樣導入導出的數(shù)據(jù)都是正確的。如果你的服務器都是處于同一時區(qū),那么是否使用 --skip-tz-utc 參數(shù)區(qū)別不大,我們只需知道默認情況 mysqldump 會將 timestamp 時間值轉為0時區(qū)存儲即可。當備份部分數(shù)據(jù)且以 timestamp 字段來篩選時,這時候建議增加 --skip-tz-utc 參數(shù)。這里再次提醒下,從全備中篩選單庫或單表的備份時,也要注意下 timestamp 字段數(shù)據(jù)。
參考:?
https://zhuanlan.zhihu.com/p/99395517
推薦閱讀
(點擊標題可跳轉閱讀)
