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 不支援外來鍵。