1. 背景mysql
* InnoDB的表空間能夠是共享的或獨立的。若是是共享表空間,則全部的表空間都放在一個文件裏:ibdata1,ibdata2..ibdataN,這種狀況下,目前應該還沒辦法實現表空間的遷移,除非徹底遷移。sql
* 無論是共享仍是獨立表空間,InnoDB每一個數據表的元數據(metadata)老是保存在 ibdata1 這個共享表空間裏,所以該文件必不可少,它還能夠用來保存各類數據字典等信息。數據庫
* 獨立表空間中數據文件單獨存放在.ibd文件中。bash
* MySQL 5.6版本開始支持獨立表空間導入與導出。ide
2. 環境 [ 2臺DB實例, MySQL 5.6表遷移至MySQL5.7 ]ui
* 源實例 MySQLspa
mysql> show variables like 'innodb%version'; +----------------+--------+ | Variable_name | Value | +----------------+--------+ | innodb_version | 5.6.36 | +----------------+--------+ 1 row in set (0.01 sec) mysql> show variables like 'datadir'; +---------------+--------------------+ | Variable_name | Value | +---------------+--------------------+ | datadir | /data/mysql_data6/ | +---------------+--------------------+ 1 row in set (0.00 sec)
* 目的實例 MySQL orm
mysql> show variables like 'innodb%version'; +----------------+--------+ | Variable_name | Value | +----------------+--------+ | innodb_version | 5.7.18 | +----------------+--------+ 1 row in set (0.00 sec) mysql> show variables like 'datadir'; +---------------+--------------------+ | Variable_name | Value | +---------------+--------------------+ | datadir | /data/mysql_data7/ | +---------------+--------------------+ 1 row in set (0.01 sec)
* 源實例 MySQL 遷移的數據庫與表信息blog
mysql> select database(); +------------+ | database() | +------------+ | mytest | +------------+ 1 row in set (0.00 sec) mysql> show create table users; +-------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | Table | Create Table | +-------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | users | CREATE TABLE `users` ( `id` bigint(20) NOT NULL AUTO_INCREMENT, `name` varchar(255) NOT NULL, `sex` enum('M','F') NOT NULL DEFAULT 'M', `age` int(11) NOT NULL DEFAULT '0', PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8mb4 | +-------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ 1 row in set (0.01 sec) mysql> select * from users; +----+-------+-----+-----+ | id | name | sex | age | +----+-------+-----+-----+ | 1 | tom | M | 25 | | 2 | jak | F | 38 | | 3 | sea | M | 43 | | 4 | lisea | M | 36 | +----+-------+-----+-----+ 4 rows in set (0.00 sec)
3. 平滑遷移實戰 [ 遷移mytest數據庫下users表 ]ip
* 目的MySQL實例建立相同的數據庫與表 [ MySQL 5.7中建立表須要指定row_format=compact ]
mysql> create database mytest character set utf8mb4; Query OK, 1 row affected (0.03 sec) mysql> use mytest; Database changed mysql> CREATE TABLE `users` ( -> `id` bigint(20) NOT NULL AUTO_INCREMENT, -> `name` varchar(255) NOT NULL, -> `sex` enum('M','F') NOT NULL DEFAULT 'M', -> `age` int(11) NOT NULL DEFAULT '0', -> PRIMARY KEY (`id`) -> ) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8mb4 row_format=compact; Query OK, 0 rows affected (0.59 sec) mysql> system ls -l /data/mysql_data7/mytest/ total 64 -rw-r----- 1 mysql mysql 67 Jul 18 05:21 db.opt -rw-r----- 1 mysql mysql 8648 Jul 18 05:21 users.frm -rw-r----- 1 mysql mysql 49152 Jul 18 05:21 users.ibd
* 目的MySQL實例丟棄表空間
mysql> alter table users discard tablespace; Query OK, 0 rows affected (0.01 sec) mysql> system ls -l /data/mysql_data7/mytest/ total 16 -rw-r----- 1 mysql mysql 67 Jul 18 05:21 db.opt -rw-r----- 1 mysql mysql 8648 Jul 18 05:21 users.frm
* 源MySQL實例刷新表至磁盤並加lock,而且當前表quiesce狀態,只讀,且建立.cfg metadata文件
mysql> flush tables users for export; Query OK, 0 rows affected (0.00 sec)
* 從源MySQL實例服務止拷貝表文件users.ibd, users.cfg文件至目的MySQL實例中
[root@MySQL ~]# cp -v /data/mysql_data6/mytest/users.{cfg,ibd} /data/mysql_data7/mytest/ `/data/mysql_data6/mytest/users.cfg' -> `/data/mysql_data7/mytest/users.cfg' `/data/mysql_data6/mytest/users.ibd' -> `/data/mysql_data7/mytest/users.ibd'
* 修改目的MySQL實例數據文件下拷貝文件的全部者與全部組
[root@MySQL ~]# chown -v mysql.mysql /data/mysql_data7/mytest/users.{cfg,ibd} changed ownership of `/data/mysql_data7/mytest/users.cfg' to mysql:mysql changed ownership of `/data/mysql_data7/mytest/users.ibd' to mysql:mysql
* 源MySQL實例釋放lock
mysql> unlock tables; Query OK, 0 rows affected (0.00 sec)
* 目的MySQL實例加載表空間
mysql> alter table users import tablespace; Query OK, 0 rows affected (0.04 sec)
* 查看目的MySQL實例表數據 [ MySQL5.6數據成功遷移過來 ]
mysql> select * from users; +----+-------+-----+-----+ | id | name | sex | age | +----+-------+-----+-----+ | 1 | tom | M | 25 | | 2 | jak | F | 38 | | 3 | sea | M | 43 | | 4 | lisea | M | 36 | +----+-------+-----+-----+ 4 rows in set (0.00 sec)
4. 注意問題
* MySQL 5.6數據遷移到MySQL5.7時,若是建立目的表時不指定row_format,import表數據時會報錯,緣由在於MySQL 5.6中是Antelope,在MySQL 5.7中是Barracuda,主要是在表壓縮和行的動態格式上有所改變。
5. 總結
以需求驅動技術,技術自己沒有優略之分,只有業務之分。