MySQL遷移通常使用的有三種方法:
1、資料庫直接導出,拷貝檔案到新伺服器,在新伺服器上導入。 2、使用第三方遷移工具。 3、資料檔案和庫表結構檔案直接拷貝到新伺服器,挂載到同樣配置的MySQL服務下。
第一種方案的優點:會重建資料檔案,減少資料檔案的占用空間,相容性最好,導出導入很少發生問題,需求靈活。缺點:使用傳統導出導入時間占用長。 第二種方案的優點:設定完成後傳輸無人值守,自動完成。缺點:不夠靈活,設定繁瑣,傳輸時間長,異常後很難從異常的位置繼續傳輸。 第三種方案的優點:時間占用短,檔案可斷點傳輸,操作步驟少。缺點:新舊伺服器中MySQL版本及配置必須相同,可能引起未知問題。
假如資料庫遷移是因為業務瓶頸或項目改造等需要變動資料表結構的(比如分區分表),我們便隻能使用第一種方法了。
操作一:本文總結各種場景下的資料複制、遷移、轉換。 1、導入、導出 利用mysqldump指令将資料檔案導出成一個文本檔案,這在不同場景下具有更高的安全性。如:表引擎改變。 資料導出:mysqldump -uroot -p dbname > dbname.sql (包含表結構和表資料) 資料導入:mysql -uroot -p dbname < dbname.sql 注意:導出的sql檔案包含舊表資訊,請修改其中的create table語句。在create之前會有一個DROP table 操作。如果沒有注意到這點,原資料就會被删除。這種情況可以用下列的sql操作: 隻導出:資料:mysqldump -uroot -p -t dbname > dbname.sql 隻導出表結構:mysqldump -uroot -p -d dbname > dbname.sql 2、将一張表的資料轉換到另一張表、并且更新表結構 a、以下sql适用于小量資料,速度快。
- mysql>create table innodb_table like myisam_table;
- mysql>alter table innodb_table engine=innodb;
- mysql>insert into innodb_table select * from myisam_table;
b、更高效的辦法是增量的填充表,在填充每個增量資料塊時都送出事務,這樣就不會導緻撤銷日志過大,假設id是主鍵,可以重複運作一下查詢(每次逐漸增大x和y值)直到所有資料都複制到新表。
- mysql>start transaction;
- mysql>insert into innodb_table select * from myisam_table where id between x and y;
- mysql>commit;
轉移操作完成後,源表仍會保留,可以在完成操作後DROP它,注意:如有必要,在轉換時加鎖源表,防止在轉換時資料不一緻。
操作二:使用MySQL的SELECT INTO OUTFILE 、LOAD DATA INFILE快速導出導入資料 LOAD DATA INFILE語句從一個文本檔案中以很高的速度讀入一個表中。MySQL官方文檔也說明了,該方法比一次性插入一條資料性能快20倍。
當使用者一前一後地使用SELECT ... INTO OUTFILE 和LOAD DATA INFILE 将資料從一個資料庫寫到一個檔案中,然後再從檔案中将它讀入資料庫中時,兩個指令的字段和行處理選項必須比對。否則,LOAD DATA INFILE 将不能正确地解釋檔案内容。
下面是一個項目的例子,MySQL由windows平台遷移到Linux平台,資料總量12G
導出到檔案中(select into outfile) SELECT fields INTO OUTFILE 'file_name' [{FIELDS | COLUMNS} 字段 [TERMINATED BY 'string' ] 字段之間分隔符号 [[OPTIONALLY] ENCLOSED BY 'char' ] 字段被包含在char中間 [ESCAPED BY 'char' ] 忽略字段裡出現的char ] [LINES [STARTING BY 'string' ] 忽略開頭是string的行 [TERMINATED BY 'string' ] 行分隔符 ] FROM test_table;
導入檔案中的資料到mysql表 LOAD DATA [LOW_PRIORITY | CONCURRENT] [LOCAL] INFILE 'file_name' [REPLACE | IGNORE] 遇到重複的時候處理方法,替換或者是忽略 INTO TABLE tbl_name 導入資料的目的表名 [PARTITION (partition_name,...)] 分區選擇 [CHARACTER SET charset_name] 字元集 [{FIELDS | COLUMNS} 字段 [TERMINATED BY 'string' ] 字段之間分隔符号 [[OPTIONALLY] ENCLOSED BY 'char' ] 字段被包含在char中間 [ESCAPED BY 'char' ] 忽略字段裡出現的char ] [LINES [STARTING BY 'string' ] 忽略開頭是string的行 [TERMINATED BY 'string' ] 行分隔符 ] [IGNORE number {LINES | ROWS}] 忽略行/列 [(col_name_or_user_var,...)] 目的表的表字段名或者使用者變量名 [SET col_name = expr ,...] 設定表字段值
Windows平台導出資料:
tables.txt是儲存資料表名稱的檔案,通過從檔案中讀取資料表名稱,循環導出所有表:如果過程中攝及到分表,可根據分表規則修改導出的sql語句和批處理代碼,非常靈活。 database 為資料庫執行個體名 @ echo off & setlocal enabledelayedexpansion for / f %% i in ( tables . txt ) do ( set table =%% i echo "dump table -- !table! --" mysql - uroot - p12345678 database - e "SELECT * INTO OUTFILE 'F:/MySQL/Uploads/!table!.txt' FIELDS TERMINATED BY ',' FROM !table!" ) pause
Linux平台導入資料: #!/bin/bash while read line do mysql - uroot - p12345678 database - e "LOAD DATA INFILE '/var/lib/mysql-files/$line.txt' INTO TABLE $line FIELDS TERMINATED BY ','" done < tables . txt
問題記錄(注意): 1.MYSQL導入資料出現The MySQL server is running with the --secure-file-priv option so it cannot execute this statement 原因:MYSQL 限制了導入與導出的目錄權限 解決辦法: 1.show variables like '%secure%'; 檢視 secure-file-priv 目前的值是什麼,将導出檔案目錄設定成secure-file-priv的值 2.修改配置可修改mysql配置檔案 檢視是否有secure_file_priv = 這樣一行内容,如果沒有,則手動添加, secure_file_priv = /home 表示限制為/home檔案夾
secure_file_priv = 表示不限制目錄,等号一定要有,否則mysql無法啟動修改完配置檔案後,重新開機mysql生效
操作三:複制檔案遷移 a->b 于是我按照網上的說法,步驟如下: 一、把機器b的mysql停掉。 二、把機器a上要遷移的庫的整個目錄複制到機器b的mysql data目錄下。 三、修改目錄權限為700,修改檔案權限為660,并修改他們的所屬使用者和所屬組為mysql。 四、到機器b上,剛才建的那個資料庫的目錄下,把所有的(.ibd)檔案删除掉。 五、把機器a上,對應資料庫目錄下所有的(.ibd)檔案複制到機器b上,修改檔案的權限。 六、再啟動機器b的mysql。 操作四五步驟的原因如下: show databases和show tables時,mysql其實是去目錄下掃描,但執行select這些操作的時候,mysql優化器會去information_schema.TABLES 這個表裡面擷取資訊。由于我們是直接複制檔案過去,是以,這個表裡面是沒有資訊的,是以就會提示表不存在。
參考文章:
1.http://www.codetc.com/article-322-1.html
2.http://blog.sina.com.cn/s/blog_59bba95d0102wspc.html