innodb compressed 表碰到的問題,BUG麼?

innodb compressed 表碰到的問題

compressed innodb 表是MySQL 5.5開始提供的功能,能夠把innodb表壓縮,對於這個操做,不少人已經說到了,主要要注意兩點:
壓縮的語法是:
alter/create table …. engine=innodb row_format=compressed key_block_size=8;
其中,row_format=compressed 表明要作壓縮表了,key_block_size可選(1,2,4,8,16),16是不壓縮,innodb的默認值,比16小都壓縮。非這幾個值的話,語句無效。mysql

同時要實現這個功能須要配置:
innodb_file_per_table
innodb_file_format = Barracudasql

另外,要注意 InnoDB 「strict mode」 的時候,也會報錯。函數

此次碰到的問題其實跟上面的沒有關係,因此,上面是廢話。測試

下面說事兒:
一個同事有個表是 row_format=compressed key_block_size=8 的,他想把它改回row_format=compact的非壓縮模式。可是碰到了問題:spa

mysql 5.5>alter table t engine =innodb row_format=compact;
ERROR 1005 (HY000): Can’t create table ‘test.#sql-684d_924′ (errno: 140 「Wrong create options」)orm

這兩個error是:
+———+——+—————————————————————————–+
| Level | Code | Message |
+———+——+—————————————————————————–+
| Warning | 140 | InnoDB: cannot specify ROW_FORMAT = COMPACT with KEY_BLOCK_SIZE. |
| Error | 1005 | Can’t create table ‘test.#sql-684d_924′ (errno: 140 「Wrong create options」) |
+———+——+—————————————————————————–+
這是在5.5下面的結果,改不回來了!ci

接下來咱們在5.6.13和MariaDB10下面測試,僅僅報了一個warning,說compact的時候不用指定 key_block_size了,這是能夠理解的。
顯然5.6作了bug修復。
經過竹峯大俠的指點,咱們來看看源碼:
這個判斷是在 storage/innobase/handler/ha_innodb.cc 裏面的create_options_are_valid函數實現的:get

在5.5裏面是這麼寫:源碼

首先定義一個變量:
ibool kbs_specified = FALSE;
而後判斷有key_block_size的話,設置kbs_specified = TRUE;
if (create_info->key_block_size) {
kbs_specified = TRUE;
…..it

}
結束這個if以後,在外面case row type:
case ROW_TYPE_COMPACT:
case ROW_TYPE_REDUNDANT:
if (kbs_specified) {
push_warning_printf(
thd, MYSQL_ERROR::WARN_LEVEL_WARN,
ER_ILLEGAL_HA_CREATE_OPTION,
「InnoDB: cannot specify ROW_FORMAT = %s」
」 with KEY_BLOCK_SIZE.」,
get_row_format_name(row_format));
ret = FALSE;
}
break;

經過上面的代碼能夠看到,在row type爲 C或者R的時候,若是kbs_specified 指定了,直接給報錯退出了!
也就是,你的語法是 create/alter table …. engine =innodb row_format=compact key_block_size=xx;
這樣的語句在5.5的時候是不能執行的,直接報錯退出。就是上面咱們看的錯誤。
那麼,若是create/alter table …. engine =innodb row_format=compact ;這樣的語句在平時沒問題,可是若是表原來是compressed的模式的,你即使不指定 key_block_size,它原來仍是存在的,也會報錯退出!

再來看看5.6的代碼,也是老地方 storage/innobase/handler/ha_innodb.cc ,只是函數名改成了create_options_are_invalid,看出區別了麼?哈哈。

實現基本同樣,也是有個變量
ibool kbs_specified = FALSE;

if (create_info->key_block_size) {
kbs_specified = TRUE;
。。。。。。
}
只是不一樣之處是:

case ROW_TYPE_COMPACT:
case ROW_TYPE_REDUNDANT:
if (kbs_specified) {
push_warning_printf(
thd, Sql_condition::WARN_LEVEL_WARN,
ER_ILLEGAL_HA_CREATE_OPTION,
「InnoDB: cannot specify ROW_FORMAT = %s」
」 with KEY_BLOCK_SIZE.」,
get_row_format_name(row_format));
ret = 「KEY_BLOCK_SIZE」;
}
break;

在case裏面,即使是發現kbs_specified,設置了 ret = 「KEY_BLOCK_SIZE」,而不是5.5裏面的False。
從而語句能順利執行。

那麼回過頭來,5.5裏面怎麼作呢?DBA能被尿憋死麼?

咱們發現,在定義的時候
ibool kbs_specified = FALSE;
這個變量設置爲true的時候是在

if (create_info->key_block_size) {
kbs_specified = TRUE;
。。。。。。
}
那麼,若是咱們的語句寫成
alter table t engine =innodb row_format=compact key_block_size=0;
是否是就沒問題了?
實踐一下,答案是YES!

這個,不知道是innodb的bug,仍是故意留的後門?這個或許只能求《走進科學》解答了。。。

相關文章
相關標籤/搜索