1. 程式人生 > >MySql 轉換表的引擎

MySql 轉換表的引擎

有很多中方法可以將表的儲存引擎轉換成另外一種引擎。我們在這隻講述其中的三種方法:

ALTER TABLE

將表從一個引擎修改為另一個引擎最簡單的辦法是使用 ALTER TABLE語句。下面的語句將 mytable的引擎修改為 INNODB:

mysql> ALTER TABLE mytable ENGINE INNODB;

上述語法可以適用任何儲存引擎。但有一個問題:需要執行很長時間。 MYSQL會按行將資料從原表複製到一張新的表中,在複製期間可能會消耗系統所有的I/O能力,同時原表上會加上讀鎖。所以,在繁忙的表上執行此操作要特別小心。一個替代方案是採用接下來將討論的匯出與匯入的方法,手工進行表的複製。

如果轉換表的儲存引檠,將會失去和原引擎相關的所有特性。例如,如果將一張 INNODB錶轉換為 MYISAM,然後再轉換回 INNODB,原 INNODB表上所有的外來鍵將丟失。

好了,當我介紹了這第一種方法後,您先別急著去實際體驗或者操作一把,因為不一定操作成功哦!啊哈哈!

下面是我的操作,反正我是操作失敗了的,這種方法並不一定會操作成功,並不好用哦!

首先我先檢視下想要操作的資料表表狀態:

使用了 show table status like 'dye_production_schedules' \G 語句。

show table status 具體語法如下:

SHOW TABLE STATUS     [{FROM | IN} db_name]     [LIKE 'pattern' | WHERE expr]

看到這裡,相比就不用我再解釋,我之前那條語句了吧!!!

其中:

Name 表示表名

Engine: 表示表的儲存引擎型別。在舊版本中,該列的名字叫Type,而不是Engine。

Version:版本 關於版本這個問題,可以參考mysql mvcc(多版本控制) ,可以參考其它文章

Row_format:行格式。對於MyISAM引擎,這可能是Dynamic,Fixed或Compressed。動態行的行長度可變,例如Varchar或Blob型別欄位。固定行是指行長度不變,例如Char和Integer型別欄位。

Rows:表中的行數。對於非事務性表,這個值是精確的,對於事務性引擎,這個值通常是估算的。

Avg_row_length:平均每行包含的位元組數

Data_length:表資料的大小 (以位元組為單位)

Max_data_length:表資料的最大容量,該值和儲存引擎有關。

Index_length:索引的大小(以位元組為單位)

Data_free:對於MyISAM 表,表示已分配但目前沒有使用的空間。這部分空間包括了之前刪除的行,以及後續可以被INSERT利用到的空間。

Auto_increment:下一個 AUTO INCREMENT的值。

Create_time:表的建立時間。

Update_time:表資料的最後修改時間

Check_time:使用 CKECK TABLE命令或者 myisamchk工具最後一次檢查表的時間。

Collation:表的預設字符集和字元列排序規則。

Cksum:如果啟用,儲存的是整個表的實時校驗和。

Create options:建立表時指定的其他選項。

Comment:該列包含了一些其他的額外資訊。對於 MYISAM表,儲存的是表在建立時帶的註釋。 對於 INNODB表,則儲存的是 INNODB表空間的剩餘空間資訊。如果是一個檢視,則 該列包含“VIEW”的文字字樣。

好的,解釋完了上條命令產生的結果集後,我們正式進入主題

mysql> alter table dye_production_schedules engine = myisam; ERROR 1292 (22007): Incorrect datetime value: '0000-00-00 00:00:00' for column 'date' at row 7994 mysql>  

納尼?為什麼在建立表的時候不報錯?為什麼?

這個不行?我換張表總可以了吧,嘿嘿!!我換成WordPress 庫表去操作!

mysql> use wordpress; Database changed mysql> show tables; +-----------------------+ | Tables_in_wordpress   | +-----------------------+ | wp_commentmeta        | | wp_comments           | | wp_links              | | wp_options            | | wp_postmeta           | | wp_posts              | | wp_term_relationships | | wp_term_taxonomy      | | wp_termmeta           | | wp_terms              | | wp_usermeta           | | wp_users              | +-----------------------+ 12 rows in set (0.00 sec)

mysql> show table status like 'wp_posts'  \G *************************** 1. row ***************************            Name: wp_posts          Engine: MyISAM         Version: 10      Row_format: Dynamic            Rows: 27  Avg_row_length: 874     Data_length: 23624 Max_data_length: 281474976710655    Index_length: 12288       Data_free: 0  Auto_increment: 28     Create_time: 2018-08-07 15:22:24     Update_time: 2018-08-07 15:26:58      Check_time: NULL       Collation: utf8mb4_unicode_520_ci        Checksum: NULL  Create_options:         Comment: 1 row in set (0.00 sec)

mysql> alter table wp_posts engine = InnoDB; ERROR 1067 (42000): Invalid default value for 'post_date' mysql>

咦?又失敗了【手動驚恐中】

算了,既然失敗了,就換種方式吧,就算是我姿勢不對,但也未免太難用了吧,換種方式。

匯出與匯入

為了更好地控制轉換的過程,可以使用 mysqldump工具將資料匯出到檔案,然後修改檔案中 CREATE TABLE語句的儲存引擎選項,注意同時修改表名,因為同一個資料庫中不能存在相同的表名,即使它們使用的是不同的儲存引擎。同時要注意 mysqldump預設會自動在 CREATE TABLE語句前加上 DROP TABLE語句,不注意這一點可能會導致資料丟失。

介紹完這種方式後,我並沒有去實踐下,理由很簡單,懶,沒錯,你沒看錯就是懶,因為mysql高效能(第三版)作者已經說了,這種方式可能會導致資料丟失,那我幹嘛還要去使用它呢?

建立與查詢( CREATE和 SELECT)

第三種轉換的技術綜合了第一種方法的高效和第二種方法的安全。不需要匯出整個表的資料,而是先建立一個新的儲存引擎的表,然後利用 INSERT-… SELECT語法來導資料

mysql> CREATE TABLE innodb_table LIKE myisam_table;

mysql> ALTER TABLE innodb table ENGINE=Innodb;

mysql> INSERT INTO innodb table SELECT *  FROM myisam table;

資料量不大的話,這樣做工作得很好。如果資料量很大,則可以考慮做分批處理,針對毎一段資料執行事務提交操作,以避免大事務產生過多的undo。假設有主鍵欄位1d,重複執行以下語句(最小值x和最大值y進行相應的替換)將資料匯入到新表:

mysql> START TRANSACTION

mysql> INSERT INTO innodb_table SELECT* FROM myisam_table WHERE id BETWEEN x AND yi

mysql> COMMIT;

這樣操作完成以後,新表是原表的一個全量複製,原表還在,如果需要可以刪除原表。如果有必要,可以在執行的過程中對原表加鎖,以確保新表和原表的資料一致。

這種方式是我推薦的,操作簡便快捷!

還是以dye_production_schedules 這個表為例,上面已經知道了它是InnoDB 引擎的,那好 ,我們就把它的儲存引擎改成MyISAM 的。

mysql> create table myisam_dye_production_schedules like  dye_production_schedules; Query OK, 0 rows affected (0.03 sec)

mysql> alter table myisam_dye_production_schedules engine = myisam; Query OK, 0 rows affected (0.03 sec) Records: 0  Duplicates: 0  Warnings: 0

mysql> insert into myisam_dye_production_schedules select * from dye_production_schedules; Query OK, 52122 rows affected, 14032 warnings (0.34 sec) Records: 52122  Duplicates: 0  Warnings: 14032

哇,幾乎是秒級別的,一下子就完成了操作,有warnnings是因為在該表中使用了外來鍵,而myisam 不支援外來鍵。