mysql數據的導入導出


2017-12-15
 
 
 

一. mysqldump工具基本用法,不適用於大數據備份

 
1. 備份所有數據庫: mysqldump -u root -p --all-databases > all_database_sql
2. 備份mysql數據庫:mysqldump -u root -p --databases mysql > mysql_database_sql
3. 備份指定的多個數據庫:mysqldump -u root -p --databases db1 db2 db3 > bak.sql
4. 備份mysql數據庫下的user表:mysqldump -u root -p mysql user > user_table
 
如果不用--databases選項,在后期進行數據還原操作時,如果該數據庫不存在,必須先創建該數據庫;而在例子3指定多個數據庫時,必須要加--databases參數,否則db2會被認為是db1庫的表。
 
把備份的所有數據文件還原:
mysql -u root -p < all_database_sql,這里不需要指定庫,因為是全部數據庫
mysql -u root -p mysql < mysql_database_sql #這里就需要指定是mysql庫了
 
 
 

二. 導出純文本數據

在某些情況下,為了一些特定的目的,經常需要將表里的數據導出為某些符號分割的純數據文本,而不是 SQL 語句,因為LOAD DATA 的加載速度比普通的 SQL 加載要快 20 倍以上

 

方法 1:使用 SELECT ...INTO OUTFILE ...命令來導出數據,具體語法如下。

mysql> SELECT * FROM tablename INTO OUTFILE 'target_file' [option];

其中 option 參數可以是以下選項:

命令參數 說明
fields terminated by '字符' 字段分隔符,默認字符為制表符'\t'
fields [optionally] enclosed by '單字符' 字段引用符,加上optionally后在數字類型上不會有引用符號
fields escaped by '單字符' 轉義字符,默認為'\'
lines starting by '字符' 每行前都加此支付,默認為空
lines terminated by '字符' 行結束符,默認為'\n'

 

 

例子1,將 emp 表中數據導出為數據文本,其中,字段分隔符為“,”,每個字段用雙引號引用起來,記錄結束符為回車符(默認如此,可以不寫)

mysql> select * from emp into outfile '/tmp/emp.txt' fields terminated by "," enclosed by '"';

輸出結果如下

mysql> system more /tmp/emp.txt
"1","z1","aa"
"2","z1","aa"
"3","z1","aa"

 

 

例子2,發現例1中第一列是數值型,如果不希望字段兩邊用引號,則語句改為如下

mysql> select * from emp into outfile '/tmp/emp.txt' fields terminated by ","  optionally enclosed by '"' ;

 結果輸出如下
mysql> system more /tmp/emp.txt
1,"z1","aa"
2,"z1","aa"
3,"z1","aa"

 

 

下面測試一下轉義字符,大概包括三類,轉義字符本身,字段分隔符(導出的文本中用什么符號分隔),記錄分隔符(每條記錄之間用什么分隔,默認是回車)

例子3,更改上面例子中id=1的name為\"##!aa

update employee  set name ='\\"##!aa' where id=1;   #更新操作中轉義字符本身也需要用轉義字符來轉義,所以這里有2個\\
# 然后做導出操作
select * from employee into outfile '/tmp/employee' fields terminated by "," optionally enclosed by ‘”’;

導出結果如下
mysql> system more /tmp/emp.txt
1,"\\\"##!aa","aa"
2,"z1","aa"
3,"z1","aa"

說明:name 中含有轉義字符本身“\”,域引用符“”“,因此,在輸出的數據中我們發現這兩種字符前面都加上了轉義字符“\”

 

例子4,將id=1的name更新為含有字段分隔符”,“的字符串

update employee set name='\\"#,#,!aa' where id=1;

然后導出
mysql> system rm /tmp/emp.txt  #需要刪掉重名文件

mysql> select * from emp into outfile '/tmp/emp.txt' fields terminated by "," optionally enclosed by '"' ;

輸出結果如下
mysql> system more /tmp/emp.txt
1,"\\\"#,#,!aa","aa"
2,"z1","aa"
3,"z1","aa"

說明:發現數據中的字符","沒有被轉義,原因是它和后面真正的字段分隔符之間沒有沖突,因為name字段包含在雙引號之間。

 

例子5:繼續做測試,將輸出文件的字段引用符去掉,這個時候,我們的預期是數據中的“,”將成為轉義字符而需要加上“\”

mysql> system rm /tmp/emp.txt
mysql> select * from emp into outfile '/tmp/emp.txt' fields terminated by "," ;

輸出結果如下

mysql> system more /tmp/emp.txt
1,\\"#\,#\,!aa,aa
2,z1,aa
3,z1,aa

說明:果然,現在的“,”前面加上了轉義字符“\”。而剛才的引用符“””卻沒有被轉義,因為它已經沒有什么歧義,不需要被轉義

 

注意:SELECT…INTO OUTFILE...產生的輸出文件如果在目標目錄下有重名文件,將不會創建成功,源文件不能被自動覆蓋

 

 

方法 2:用 mysqldump 導出數據為文本。

mysqldump –u username –T target_dir dbname tablename [option]

其中 option 參數可以是以下選項:

1) --fields-terminated-by=name(字段分隔符);
2) --fields-enclosed-by=name  字段引用符,比如每個字段用雙引號括起來;
3) --fields-optionally-enclosed-by=name(字段引用符,只用在 char、varchar 和 text 等字符型字段上
4) --fields-escaped-by=name(轉義字符);
5) --lines-terminated-by=name(記錄結束符)。

 

常用參數
 --compact :使得輸出結果簡潔,不包括默認選項中的各種注釋,例如例中對 test 數據庫中的表 emp 進行簡潔導出 mysqldump -uroot -p  --compact test emp >a

 -F --flush-logs(備份前刷新日志):加上此選項后,備份前將關閉舊日志,生成新日志。使得進行恢復的時候直接從新日志開始進行重做,大大方便了恢復過程

 -l --lock-tables(給所有表加讀鎖):可以在備份期間使用,使得數據無法被更新,從而使備份的數據保持一致性,可以配合-F選項一起使用。

 

注意:

MyISAM 存儲引擎在備份的時候需要加上-l 參數,表示將所有表加上讀鎖,在備份期間,所有表將只能讀而不能進行數據更新。

但是對於事務存儲引擎(InnoDB 和 BDB)來說,可以采用更好的選項--single-transaction,此選項將使得 InnoDB 存儲引擎得到一個快照(Snapshot),使得備份的數據能夠保證一致性

 

例子,采用 mysqldump 生成指定分隔符分隔的文本:

mysqldump -uroot -T /tmp test emp --fields-terminated-by ',' --fields-optionally-enclosed-by '"'

輸出結果如下

more /tmp/emp.txt

1,"\\\"#,#,!aa","aa"
2,"z1","aa"
3,"z1","aa"

 

注意:

1)ubuntu測試中會出錯,解決方法如下。將輸出目錄改為/var/lib/mysql-files/. 例子中test是庫名,emp是表名,如果不寫則備份全部表

mysql> mysql> select * from person into outfile '/tmp/x.txt' fields terminated by ",";
ERROR 1290 (HY000): The MySQL server is running with the --secure-file-priv option so it cannot execute this statement
mysql> show global variables like "%secure%";
+--------------------------+-----------------------+
| Variable_name            | Value                 |
+--------------------------+-----------------------+
| require_secure_transport | OFF                   |
| secure_auth              | ON                    |
| secure_file_priv         | /var/lib/mysql-files/ |
+--------------------------+-----------------------+

 

2)如果非要用/tmp,則需要做如下操作 (測試了下又不行了...)

在/etc/apparmor.d/usr.sbin.mysqld文件中加入一行代碼如下
/data/export/** rw, 保存退出后
/etc/init.d/apparmor reload  #重新載入配置 
再次導出即可。

 

 

 

 

三. 導入純文本數據

這里只討論用 SELECT… INTO OUTFILE 或者 mysqldump 導出的純數據文本的導入方法。和導出類似,導入也有兩種不同的方法,分別是 LOAD DATA INFILE…和mysqlimport,它們的本質是一樣的,區別只是在於一個在 MySQL 內部執行,另一個在 MySQL 外部執行。

 

需要注意的是在導入純文本數據之前,需要事先創建好表結構

1. 一個簡單的完整例子

首先准備表結構和文本數據,新建test庫:create database test,然后在test下新建表person

create table person(  
id int not null auto_increment,  
name varchar(40) not null,  
city varchar(20),  
salary int,  
primary key(id)  
)
engine=innodb default charset=utf8; 

 

張三  北京  3000 
李四  杭州  4000 
王五  /N  4500 
小明  天津  /N

每一項之間用Tab鍵進行分隔,如果該字段為NULL,則用/N表示。

 

進入mysql並且切換到對應的庫后,執行下面命令導入數據:

load data local infile  "/var/lib/mysql/test/data.txt"  into table person(name,city,salary); 

 

注意

1. data.txt存放的位置,其他地方會報錯

2. 在mysql配置文件中修改字符編碼

mysql 5.6
sudo vim /etc/mysql/my.cnf,重啟mysql來完成字符集的設置。添加以下兩行 (如果是上傳安裝包,vim /etc/my.cnf)
[mysqld]
character_set_server=utf8
binlog_format=row

mysql 5.7 可能需要在etc/mysql/mysql.conf.d/mysqld.cnf中額外增加如下代碼,有時候也不需要
[client]
default-character-set=utf8

 

 

2. 使用“LOAD DATA INFILE…”命令導入數據詳解

mysql > LOAD DATA [LOCAL] INFILE ‘filename’ INTO TABLE tablename [option]

option 可以是以下選項:
1. FIELDS TERMINATED BY 'string'(字段分隔符,默認為制表符'\t')
2. FIELDS [OPTIONALLY] ENCLOSED BY 'char'   字段引用符,如果加 OPTIONALLY 選項則只會做用在char, varchar和text等字符型字段上,其他類型字段默認不使用引用符
3. FIELDS ESCAPED BY 'char'(轉義字符,默認為'\');
4. LINES STARTING BY 'string'(每行前都加此字符串,默認'');
5. LINES TERMINATED BY 'string'(行結束符,默認為'\n');
6. IGNORE number LINES(忽略輸入文件中的前 n 行數據);
7. (col_name_or_user_var,...) (按照列出的字段順序和字段數量加載數據);
8. SET col_name = expr,... 將列做一定的數值轉換后再加載。

 

注意:
1. 其中 char 表示此符號只能是單個字符,string 表示可以是字符串。
2. FILELD 和 LINES 和前面 SELECT …INTO OUTFILE…的含義完全相同,不同的是多了幾個不同的選項

 

例子1:將文件“/tmp/emp.txt”中的數據加載到表 emp 中

mysql> load data infile '/tmp/emp.txt' into table emp fields terminated by ',' enclosed by'"' ;

 

例子2:如果不希望加載文件中的前2行,加上ignore字段

mysql> load data infile '/tmp/emp.txt' into table emp fields terminated by ','  enclosed by '"'  ignore 2 lines;

 

例子3:如果發現文件中的列順序和表中的列順序不符,或者只想加載部分列,可以在命令行中加上列的順序

mysql> load data infile '/tmp/emp.txt' into table emp fields terminated by ',' enclosed by '"' ignore 2 lines (id,content,name);

如果只想加載第一列,字段的列表里面可以只加第一列的名稱:

mysql> load data infile '/tmp/emp.txt' into table emp fields terminated by ',' enclosed by '"'  ignore 2 lines (id);

 

例子4:如果希望將 id 列的內容+10 后再加載到表中,可以如下操作:

mysql> load data infile '/tmp/emp.txt' into table emp fields terminated by ','  enclosed by '"'  set id=id+10;

 

 

3. 用 mysqlimport 來實現導入數據詳解,具體命令如下


shell>mysqlimport –u root –p*** [--LOCAL] dbname order_tab.txt [option]
其中 option 參數可以是以下選項:
1.  --fields-terminated-by=name(字段分隔符);
2.  --fields-enclosed-by=name(字段引用符);
3.  --fields-optionally-enclosed-by=name(字段引用符,只用在 char、varchar 和 text 等字符型字段上
4.  --fields-escaped-by=name(轉義字符);
5.  --lines-terminated-by=name(記錄結束符);
6.  -- ignore-lines=number(或略前幾行)。


這與 mysqldump 的選項幾乎完全相同,這里不再詳細介紹,簡單來看一個例子:

mysqlimport -uroot test /tmp/emp.txt --fields-terminated-by=',' --fields-enclosed-by='"'

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM