當心!使用mysqldump備份可能會讓你欲哭無淚
1
問題描述
在一次使用mysqldump備份單表部分資料時,發現無備份資料。陣針對這一奇怪現象,進行分析。
2
問題復現與分析
#表結構資訊 mysql> show create table test.t1; +-------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | Table | Create Table | +-------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | t1 | CREATE TABLE `t1` ( `id` int(11) NOT NULL AUTO_INCREMENT, `time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (`id`), KEY `idx_t` (`time`) ) ENGINE=InnoDB AUTO_INCREMENT=16 DEFAULT CHARSET=utf8 | +-------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ 1 row in set (0.00 sec) #表資料資訊 mysql> select * from test.t1; +----+---------------------+ | id | time | +----+---------------------+ | 1 | 2018-12-10 22:15:39 | | 2 | 2018-12-10 22:15:47 | | 3 | 2018-12-10 22:15:50 | | 4 | 2018-12-10 22:15:56 | | 5 | 2018-12-10 22:15:57 | | 6 | 2018-12-10 22:15:58 | | 7 | 2018-12-10 22:15:58 | | 8 | 2018-12-10 22:16:06 | | 9 | 2018-12-10 22:16:06 | | 10 | 2018-12-10 22:16:07 | | 11 | 2018-12-10 22:16:08 | | 12 | 2018-12-10 22:16:13 | | 13 | 2018-12-10 22:16:13 | | 14 | 2018-12-10 22:16:14 | | 15 | 2018-12-10 22:16:15 | +----+---------------------+ 15 rows in set (0.00 sec)
使用mysqldump --where選項備份t1表部分資料。
#使用mysqldump根據time列條件備份 mysqldump -uroot -p123456 --default-character-set=utf8 -q --master-data=2 --single-transaction --databases test --tables t1 --where "time>'2018-12-10 22:16:08'">beifen.sql #透過備份檔案可以看出備份結果中並無資料。 ... LOCK TABLES `t1` WRITE; /*!40000 ALTER TABLE `t1` DISABLE KEYS */; /*!40000 ALTER TABLE `t1` ENABLE KEYS */; UNLOCK TABLES; ...
在MySQL中使用相同條件查詢,並無異常,可以查到資料。
[root@master ~]# mysql -uroot -p123456 -e "select * from test.t1 where time>'2018-12-10 22:16:08'" mysql: [Warning] Using a password on the command line interface can be insecure. +----+---------------------+ | id | time | +----+---------------------+ | 12 | 2018-12-10 22:16:13 | | 13 | 2018-12-10 22:16:13 | | 14 | 2018-12-10 22:16:14 | | 15 | 2018-12-10 22:16:15 | +----+---------------------+
嘗試備份t1全表資料
mysqldump -uroot -p123456 --default-character-set=utf8 -q --master-data=2 --single-transaction --databases test --tables t1 >beifen.sql #有資料,但是仔細對照,我們可以發現時間回退了八個小時。 LOCK TABLES `t1` WRITE; /*!40000 ALTER TABLE `t1` DISABLE KEYS */; INSERT INTO `t1` VALUES (1,'2018-12-10 14:15:39'),(2,'2018-12-10 14:15:47'),(3,'2018-12-10 14:15:50'),(4,'2018-12-10 14:15:56'),(5,'2018-12-10 14:15:57'),(6,'2018-12-10 14:15:58'),(7,'2018-12-10 14:15:58'),(8,'2018-12-10 14:16:06'),(9,'2018-12-10 14:16:06'),(10,'2018-12-10 14:16:07'),(11,'2018-12-10 14:16:08'),(12,'2018-12-10 14:16:13'),(13,'2018-12-10 14:16:13'),(14,'2018-12-10 14:16:14'),(15,'2018-12-10 14:16:15'); /*!40000 ALTER TABLE `t1` ENABLE KEYS */; UNLOCK TABLES; #檢視mysqldump備份檔案頭部資訊,mysqldump使用的是中時區。 ... /*!40103 SET TIME_ZONE='+00:00' */; ... #檢視MySQL和系統時區。 mysql> show variables like '%time%'; +---------------------------------+-------------------+ | Variable_name | Value | +---------------------------------+-------------------+ | binlog_max_flush_queue_time | 0 | | connect_timeout | 10 | | datetime_format | %Y-%m-%d %H:%i:%s | | default_password_lifetime | 0 | | delayed_insert_timeout | 300 | | explicit_defaults_for_timestamp | OFF | | flush_time | 0 | | have_statement_timeout | YES | | innodb_flush_log_at_timeout | 1 | | innodb_lock_wait_timeout | 50 | | innodb_old_blocks_time | 1000 | | innodb_rollback_on_timeout | OFF | | interactive_timeout | 28800 | | lc_time_names | en_US | | lock_wait_timeout | 31536000 | | log_timestamps | UTC | | long_query_time | 10.000000 | | max_execution_time | 0 | | net_read_timeout | 30 | | net_write_timeout | 60 | | rpl_semi_sync_master_timeout | 10000 | | rpl_stop_slave_timeout | 31536000 | | slave_net_timeout | 60 | | slow_launch_time | 2 | | system_time_zone | CST | | time_format | %H:%i:%s | | time_zone | +08:00 | | timestamp | 1544775697.554299 | | wait_timeout | 28800 | +---------------------------------+-------------------+ 29 rows in set (0.01 sec) [root@master ~]# date -R Wed, 12 Dec 2018 16:00:34 +0800 #模擬資料恢復 mysql> drop table test.t1; mysql -uroot -p123456<beifen mysql> select * from t1; +----+---------------------+ | id | time | +----+---------------------+ | 1 | 2018-12-10 22:15:39 | | 2 | 2018-12-10 22:15:47 | | 3 | 2018-12-10 22:15:50 | | 4 | 2018-12-10 22:15:56 | | 5 | 2018-12-10 22:15:57 | | 6 | 2018-12-10 22:15:58 | | 7 | 2018-12-10 22:15:58 | | 8 | 2018-12-10 22:16:06 | | 9 | 2018-12-10 22:16:06 | | 10 | 2018-12-10 22:16:07 | | 11 | 2018-12-10 22:16:08 | | 12 | 2018-12-10 22:16:13 | | 13 | 2018-12-10 22:16:13 | | 14 | 2018-12-10 22:16:14 | | 15 | 2018-12-10 22:16:15 | +----+---------------------+ 15 rows in set (0.00 sec) #資料恢復正常。但是存在一個問題,因為mysqldump備份時會把資料進行時區轉換,導致mysqldump過濾條件與篩選的資料差8個小時,所以可能會使where條件過濾不準確。比如文章開頭所碰到的問題。
解決辦法
#使用--skip-tz-utc,不使用mysqldump預設的中時區。 mysqldump --default-character-set=utf8 -q --master-data=2 --single-transaction --databases test --tables t1 --where "time='2018-12-10 22:16:08'" -uroot -p123456 --skip-tz-utc>beifen.sql #資料完全正確,檔案頭部無時區轉換,所以資料恢復時正常。 LOCK TABLES `t1` WRITE; /*!40000 ALTER TABLE `t1` DISABLE KEYS */; INSERT INTO `t1` VALUES (11,'2018-12-10 22:16:08'); /*!40000 ALTER TABLE `t1` ENABLE KEYS */; UNLOCK TABLES;
3
總結
在使用mysqldump備份含有timestamp型別列的表時,需要指定--skip-tz-utc選項,否則可能會導致備份資料異常。(推薦使用datetime,與時區無關且儲存範圍更大,可以避免一些問題。)
| 作者簡介
薛世傑·沃趣科技資料庫工程師
熟悉MySQL體系結構和innodb儲存引擎工作原理;擅長資料庫問題分析,備份恢復、SQL調優;喜好鑽研開源技術,熟悉多種開源工具。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/28218939/viewspace-2636876/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 科技圈承包法蘭克福國際車展,傳統廠商欲哭無淚
- 【mysqldump】mysqldump及備份恢復示例MySql
- Mysqldump的備份流程MySql
- MySQLDump的備份方法MySql
- mysqldump備份技巧分享MySql
- 安卓使用者當心啦 這個App可能會偷走你的比特幣安卓APP比特幣
- windows mysqldump備份指令碼WindowsMySql指令碼
- 當心!你的App 可能是山寨的APP
- 使用Mysqldump備份和恢復MySQL資料庫MySql資料庫
- 簡單的mysqldump備份(windows)MySqlWindows
- mysqldump 資料庫備份程式MySql資料庫
- Mysqldump 在備庫進行備份時會阻塞備庫的sql_threadMySqlthread
- 詳解MySQL資料備份之mysqldump使用方法MySql
- mysql5.6 mysqldump備份報錯MySql
- MySQL主從配置及mysqldump備份MySql
- mysqldump全量備份+mysqlbinlog二進位制日誌增量備份MySql
- mysqldump使用方法(MySQL資料庫的備份與恢復)MySql資料庫
- mysqldump壓縮備份匯出匯入(含定期備份shell指令碼)MySql指令碼
- mysqldump+mysqlbinlog執行備份與還原MySql
- Linux基礎命令---mysqldump資料庫備份LinuxMySql資料庫
- Mysql備份和還原資料庫-mysqldumpMySql資料庫
- 不要讓你的檔案“失蹤”,學會小米手機怎麼備份
- Mysqldump備份說明及資料庫備份指令碼分享-運維筆記MySql資料庫指令碼運維筆記
- windows下使用mysqldump備份資料庫並上傳到阿里雲OSSWindowsMySql資料庫阿里
- 『無為則無心』Python基礎 — 43、檔案備份的實現Python
- 讓 sudo 會話時間隨心所欲會話
- 讓無數主播當場落淚,滿分神作《去月球》是如何講故事的?
- 當心,你收到的疫情相關郵件可能是病毒攻擊
- 讓資料為你帶來無限可能性
- 7 天后,讓掘金開發者大會帶你探索微信小程式的無限可能!微信小程式
- N天后,讓掘金開發者大會帶你探索微信小程式的無限可能!微信小程式
- 關於mysqldump備份非事務表的注意事項MySql
- mysqldump備份單庫、部分庫、全庫、及排除部分庫MySql
- 當心 Collection 的 slice 方法,它會偷偷修改你的陣列陣列
- 不管你是笑是哭看哪裡,這個神經網路都能讓你面無表情神經網路
- mysqldump備份時如何保持資料的一致性MySql
- CommandLineRunner 可能會導致你的應用當機停止,我勸你耗子尾汁
- mysqldump 備份匯出資料排除某張表或多張表MySql