【问题标题】:MySQL row size too large, but only in 5.7MySQL 行大小太大,但仅在 5.7
【发布时间】:2018-05-18 18:30:07
【问题描述】:

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

  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 中成功?

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

【问题讨论】:

    标签: mysql ruby-on-rails-4


    【解决方案1】:

    字符类型列的字符集,特别是 url VARCHAR 列。

    数据类型定义VARCHAR(16383) 的长度属性指定了字符数

    但 InnoDB 行大小限制以 字节 为单位。

    对于单字节字符集(例如 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 中的默认字符集不同。

    【讨论】:

    • 是的,就是这样:5.6 系统将其作为 utf8,而 5.7 系统将其作为 utf8mb4。 (在 3 个字节/字符的情况下,它仍然适合。)
    • @DavidMoles:很高兴你找到它。解决方法是返回 utf8 字符集,或缩短 VARCHAR 列中的字符数 (16383*3/4) ...或更改为允许在溢出页面上“行外”存储的数据类型。
    猜你喜欢
    • 2019-05-17
    • 2021-02-03
    • 2021-04-11
    • 2016-02-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-08-12
    • 1970-01-01
    相关资源
    最近更新 更多