對於越來越多的數據,數據庫的容量越來越大,壓縮也就越來越常見了。在我的實際工作中進行過多次壓縮工作,也遇到多次問題,在此和大家分享一下。
首先,我們先說說怎么使用innodb的壓縮.
第一,mysql的版本需要大於5.5 第二,設置innodb_file_format=barracuda 第三,create table或者alter talble 增加 ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=8;(默認的key_block_size=16)
其實很簡單,根據經驗,一般壓縮比例可以達到30%-40%
然后,我們說說我在壓縮過程中遇到的坑和發現的關聯,當然有些比較二。
No1:
問題:使用腳本批量alter操作,只動態修改了實例的innodb_file_format=barracuda,然后alter所有數據庫中的表。並沒有修改配置文件中的設置。
結果:表中已有數據被壓縮,但是在重啟之后,由於innodb_file_format參數被重新修改成antelope,導致后續寫入的數據沒有被壓縮(雖然表結構中有row_format=compressed,但是不會起作用),最終表體積仍然很大。
教訓:實例和配置文件要同步修改。(這個錯誤最二,太低級 T_T,不解釋了。)
No2:
問題:在innodb_file_format=antelope的情況下,建立壓縮表(表結構中帶有row_format=compressed),然后在設置innodb_file_format=barracuda。
結果:表結構中的row_format=compressed被忽略,后續寫入表的數據並沒有被壓縮,最終導致表體積大。
教訓:先修改innodb_file_format(session和global都需要修改),在create table或者alter table。
但是以上這點有個坑人的地方,在錯誤的順序下,表是可以被成功建立了,只是會有warning,但是表結構中會有row_format=compressed,在后期排查的時候非常誤導人!
+--------------------------+----------+ | Variable_name | Value | +--------------------------+----------+ | innodb_file_format | Antelope | | innodb_file_format_check | ON | | innodb_file_format_max | Antelope | +--------------------------+----------+ 3 rows in set (0.00 sec)
test> create table test_1 (x int) ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=8;
Query OK, 0 rows affected, 4 warnings (0.07 sec)
test> show warnings;
+---------+------+-----------------------------------------------------------------------+
| Level | Code | Message |
+---------+------+-----------------------------------------------------------------------+
| Warning | 1478 | InnoDB: KEY_BLOCK_SIZE requires innodb_file_format > Antelope. |
| Warning | 1478 | InnoDB: ignoring KEY_BLOCK_SIZE=8. |
| Warning | 1478 | InnoDB: ROW_FORMAT=COMPRESSED requires innodb_file_format > Antelope. |
| Warning | 1478 | InnoDB: assuming ROW_FORMAT=COMPACT. |
+---------+------+-----------------------------------------------------------------------+
4 rows in set (0.00 sec)
我們可以從warnings中看見,壓縮設置被忽略了。但是最坑爹的一點是,如果我們show create table會有如下結果:
test_1 | CREATE TABLE `test_1` ( `x` int(11) DEFAULT NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=8
在這種情況下,我們吸取教訓,不能使用show create table看壓縮狀態,而是應該用show table status;
show table status like 'test_1'\G; *************************** 1. row *************************** Name: test_1 Engine: InnoDB Version: 10 Row_format: Compact Rows: 0 Avg_row_length: 0 Data_length: 16384 Max_data_length: 0 Index_length: 0 Data_free: 0 Auto_increment: NULL Create_time: 2013-09-27 15:59:13 Update_time: NULL Check_time: NULL Collation: utf8_general_ci Checksum: NULL Create_options: row_format=COMPRESSED KEY_BLOCK_SIZE=8 Comment: 1 row in set (0.00 sec)
坑爹啊,不說了。正常應該這個樣子
show table status like 'test_2'\G; *************************** 1. row *************************** Name: test_2 Engine: InnoDB Version: 10 Row_format: Compressed Rows: 0 Avg_row_length: 0 Data_length: 8192 Max_data_length: 0 Index_length: 0 Data_free: 0 Auto_increment: NULL Create_time: 2013-09-27 16:09:51 Update_time: NULL Check_time: NULL Collation: utf8_general_ci Checksum: NULL Create_options: row_format=COMPRESSED KEY_BLOCK_SIZE=8 Comment: 1 row in set (0.00 sec)
No3:
發現和innodb_file_format相關的2個參數:
+--------------------------+-----------+ | Variable_name | Value | +--------------------------+-----------+ | innodb_file_format | Barracuda | | innodb_file_format_check | ON | | innodb_file_format_max | Barracuda | +--------------------------+-----------+ 3 rows in set (0.00 sec)
官方的解釋可以參考如下的鏈接:http://dev.mysql.com/doc/refman/5.5/en/innodb-parameters.html#sysvar_innodb_file_format
測試過程中發現,如果是innodb_file_format=barracuda而innodb_file_format_max=antelop,那么在建立壓縮表的時候,max會自動變成barracuda。
localhost.test>show global variables like 'innodb_file_format%'; +--------------------------+-----------+ | Variable_name | Value | +--------------------------+-----------+ | innodb_file_format | Barracuda | | innodb_file_format_check | ON | | innodb_file_format_max | Antelope | +--------------------------+-----------+ 3 rows in set (0.00 sec) localhost.test>create table test_4(x int) ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=8; Query OK, 0 rows affected (0.01 sec) localhost.test>show global variables like 'innodb_file_format%'; +--------------------------+-----------+ | Variable_name | Value | +--------------------------+-----------+ | innodb_file_format | Barracuda | | innodb_file_format_check | ON | | innodb_file_format_max | Barracuda | +--------------------------+-----------+ 3 rows in set (0.00 sec)
如果innodb_file_format_check這參數解釋的,決定innodb是否會檢查共享表空間中的表格式的tag,如果檢查開啟,那么當標記的表格式的tag高於innodb可以支撐的表格式,那么innodb會報錯,並停止啟動。如果支持,那么會將innodb_file_format_max的值改為這個tag的值。