眾所周知,mysqldump不但可以導出sql格式,還可以導出csv格式。
導出CSV格式的具體使用如下命令。
mysqldump -uroot -ppassword -S /tmp/mysql9991.sock heartbeat -t -T /data1/mysql9991/
導出后,會生成2個文件,一個tablename.sql為表結構,另一個tablename.txt為數據內容。
需要注意的是:
1、-T 參數跟的是目錄path,不是文件名。
2、這個path必須是導出源mysql具有可寫權限的,否則報錯如下。
mysqldump -uroot -ppassword -S /tmp/mysql9991.sock heartbeat alive -t -T /data1/ mysqldump: Got error: 1: Can't create/write to file '/data1/alive.txt' (Errcode: 13) when executing 'SELECT INTO OUTFILE'
3、使用的用戶需要有select和file2個權限。
4、使用fields-terminated-by和lines-terminated-by可以自定義字段分割符和行分隔符
5、mysqldump導出csv格式只能在本地進行,無法遠程操作。
但是很少有人知道mysqldump可以支持where條件導出,具體的方法如下:
mysqldump -uroot -ppassword -S /tmp/mysql9991.sock heartbeat alive -w "time between '2013-12-22 00:00:00' and '2013-12-22 23:59:59'" > 1.txt
或者
mysqldump -uroot -ppassword -S /tmp/mysql9991.sock heartbeat alive -w "time between '2013-12-22 00:00:00' and '2013-12-22 23:59:59'" -t -T /data1/mysql9991/
最近利用利用這個特性在導出一個時間段的數據的時候突然發現遇到如下問題:
### 首先使用如下命令導出數據
mysqldump -uroot -ppasswrod -S /tmp/mysql9991.sock heartbeat alive -w "time between '2013-12-22 00:00:00' and '2013-12-22 23:59:59'" > 1.txt
### 查看內容ok
INSERT INTO `alive` VALUES ('2013-12-22 00:00:00','2013-12-22 00:00:00')...................省略n多內容。
### 重新導入庫中后發現,內容變了
source 1.txt
select * from alive limit 3;
+---------------------+---------------------+
| time | systime |
+---------------------+---------------------+
| 2013-12-22 08:00:00 | 2013-12-22 08:00:00 |
| 2013-12-22 08:00:01 | 2013-12-22 08:00:01 |
| 2013-12-22 08:00:02 | 2013-12-22 08:00:02 |
+---------------------+---------------------+
3 rows in set (0.00 sec)
從上面我們可以看到,sql文件中的時間是12月22日0點0分0秒,那么為什么重新灌入庫中就變成了12月22日8點0分0秒了呢?
聰明的同學應該已經反應出來了,8小時是標准的時區設置,這必然和時區有關。man一下mysqldump之后發現果然和時區有關,有個關鍵參數是--tz-utc這個參數解釋如下:
--tz-utc This option enables TIMESTAMP columns to be dumped and reloaded between servers in different time zones. mysqldump sets its connection time zone to UTC and adds SET TIME_ZONE=’+00:00’ to the dump file. Without this option, TIMESTAMP columns are dumped and reloaded in the time zones local to the source and destination servers, which can cause the values to change. --tz-utc also protects against changes due to daylight saving time. --tz-utc is enabled by default. To disable it, use --skip-tz-utc. This option was added in MySQL 5.0.15.
從解釋中看到,默認--tz-utc是打開的,而這個參數會影響timestamp的。他會默認設置時區為time_zone=‘+00:00’,而由於我們所在的時區是‘+08:00’所以自然會增加8個小時。(所在時區可以使用date +%z查詢)
如解釋中可以使用--skip-tz-utc來解決這個問題,我們重新dump一次,對比兩次的文件可以更明顯的看出來,沒有添加參數的多出了time zone的配置。
### 第一次沒有加參數的配置 /*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; /*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; /*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; /*!40101 SET NAMES utf8 */; /*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; /*!40103 SET TIME_ZONE='+00:00' */; /*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; /*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; /*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; ### 第二次添加 --skip-tz-utc /*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; /*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; /*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; /*!40101 SET NAMES utf8 */; /*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; /*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; /*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
至此,問題解決。
突然發現,即使是我們經常使用的命令,依然有很多不知道的參數,看來還需要多多研究,另外就是,善用man,其實問題的解決方法都已經放在了哪里。
