MySQL行的大小太大,但只有5.7

时间:2018-05-18 18:30:08

标签: mysql ruby-on-rails-4

当我使用rake db:schema:load在运行MySQL 5.6.22的笔记本电脑上创建下表时,它加载正常:

  create_table "inv_audits", force: :cascade do |t|
    t.integer  "inv_node_id",         limit: 2,                         null: false
    t.integer  "inv_object_id",       limit: 4,                         null: false
    t.integer  "inv_version_id",      limit: 4,                         null: false
    t.integer  "inv_file_id",         limit: 4,                         null: false
    t.string   "url",                 limit: 16383
    t.string   "status",              limit: 18,    default: "unknown", null: false
    t.datetime "created",                                               null: false
    t.datetime "verified"
    t.datetime "modified"
    t.integer  "failed_size",         limit: 8,     default: 0,         null: false
    t.string   "failed_digest_value", limit: 255
    t.text     "note",                limit: 65535
  end

但是,当我尝试在运行5.7.21的桌面上执行相同的操作时,它会失败并显示Mysql2::Error: Row size too large.

跟踪生成的SQL是:

CREATE TABLE `inv_audits` (
  `id`                  int(11) auto_increment PRIMARY KEY,
  `inv_node_id`         smallint                      NOT NULL,
  `inv_object_id`       int(11)                       NOT NULL,
  `inv_version_id`      int(11)                       NOT NULL,
  `inv_file_id`         int(11)                       NOT NULL,
  `url`                 varchar(16383),
  `status`              varchar(18) DEFAULT 'unknown' NOT NULL,
  `created`             datetime                      NOT NULL,
  `verified`            datetime,
  `modified`            datetime,
  `failed_size`         bigint DEFAULT 0              NOT NULL,
  `failed_digest_value` varchar(255),
  `note`                text
) ENGINE=InnoDB

为什么这会在5.7中失败但在5.6中成功?

两台机器都是64位Mac,运行macOS High Sierra(10.13.4)。

1 个答案:

答案 0 :(得分:4)

字符类型列的字符集,尤其是url VARCHAR列。

数据类型定义VARCHAR(16383)上的length属性指定了多个字符

但InnoDB行大小限制为 bytes

对于单字节字符集(例如latin1),该列的最大字节数为16383(加上隐藏长度的空间)。这没关系。

使用多字节字符集,例如utf8(每个字符最多3个字节)或utf8mb4(每个字符最多4个字节),所需的字节数将超过InnoDB行的最大允许字节数。

在5.6系统上,我们可以做一个

 SHOW CREATE TABLE inv_audits

如果没有为列指定字符集/排序规则,则表的默认值有效。 (可以指定表的字符集,如果不是,则继承数据库的默认集。)

要获取在5.7上创建的表,作为测试,将VARCHAR大小减小到当前值的1/4,然后查看CREATE TABLE。

 SHOW CREATE TABLE inv_audits

它将是一个多字节字符集,如utf8或utf8mb4。

我敢打赌,问题的根本原因是默认字符集在5.6和5.7中是不同的。