zoukankan      html  css  js  c++  java
  • 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小都压缩。非这几个值的话,语句无效。

    同时要实现这个功能需要配置:
    innodb_file_per_table
    innodb_file_format = Barracuda

    另外,要注意 InnoDB “strict mode” 的时候,也会报错。

    这次碰到的问题其实跟上面的没有关系,所以,上面是废话。

    下面说事儿:
    一个同事有个表是 row_format=compressed key_block_size=8 的,他想把它改回row_format=compact的非压缩模式。但是碰到了问题:

    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”)

    这两个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下面的结果,改不回来了!

    接下来我们在5.6.13和MariaDB10下面测试,仅仅报了一个warning,说compact的时候不用指定 key_block_size了,这是可以理解的。
    显然5.6做了bug修复。
    通过竹峰大侠的指点,我们来看看源码:
    这个判断是在 storage/innobase/handler/ha_innodb.cc 里面的create_options_are_valid函数实现的:

    在5.5里面是这么写:

    首先定义一个变量:
    ibool kbs_specified = FALSE;
    然后判断有key_block_size的话,设置kbs_specified = TRUE;
    if (create_info->key_block_size) {
    kbs_specified = TRUE;
    …..

    }
    结束这个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,还是故意留的后门?
    这个或许只能求《走进科学》解答了。。。

  • 相关阅读:
    面向对象程序设计(JAVA) 第11周学习指导及要求
    面向对象程序设计(JAVA) 第10周学习指导及要求
    国内外计算机教育领域顶会、权威期刊名录
    面向对象程序设计(JAVA) 第8周学习指导及要求
    JAVA类与类之间的关系及代码示例
    面向对象程序设计(Java) 第7周学习指导及要求
    面向对象程序设计(Java) 第6-7周学习指导及要求
    面向对象程序设计(Java) 第4周学习指导及要求
    面向对象程序设计(Java) 第2周学习指导及要求
    前端开发基础,JavaScript 主要作用是什么?
  • 原文地址:https://www.cnblogs.com/bamboos/p/3338500.html
Copyright © 2011-2022 走看看