MySQL - 在InnoDB 中 Troubleshooting Row size too large (」 8126)

解决报错

遇到报错:

ERROR 1118 (42000): Row size too large (> 8126). Changing some columns to TEXT or BLOB or using ROW_FORMAT=DYNAMIC or ROW_FORMAT=COMPRESSED may help. In current row format, BLOB prefix of 768 bytes is stored inline.
ERROR 1118 (42000): Row size too large. The maximum row size for the used table type, not counting BLOBs, is 8126. This includes storage overhead, check the manual. You have to change some columns to TEXT or BLOBs

root cause:
MySQL的页大小如果为 16K,一个页中至少要存两行数据。那么每一行的大小是不能超过 8126字节,超出的部分,会放在其他页中,这个页称为 溢出页(overflow page),这些列称为 off-page columns。

当使用行格式为 compact 时,碰到字段内容超过 767 字节 的内容时,会将前 767 字节放入主页中,再存储一个 20字节 的指针信息,将剩余的部分放入到其他的数据页中。

所以,在行格式为 compact 时,blob列多于十个时,并且每一列的数据内容都多于 767字节。 这样的话,每一行最小占据的字节数量也会多于 8126。就会超过限制。

当然,如果设置 blob 多于 10 个列,每一列的数据没有超过767,并且相加没有超过 8126 字节,也是不会报错的。

解决方案:
将表的 row_format 改为 dynamic 即可。

实验:

-- t1 十个列
MySQL [testdb]> create table t1(
    -> id int primary key
    -> , col1 longblob
    -> , col2 longblob
    -> , col3 longblob
    -> , col4 longblob
    -> , col5 longblob
    -> , col6 longblob
    -> , col7 longblob
    -> , col8 longblob
    -> , col9 longblob
    -> , col10 longblob
    -> ) charset=utf8 row_format=compact;
Query OK, 0 rows affected (0.04 sec)

MySQL [testdb]> insert into t1 values (1,
    -> repeat('a',1000),repeat('a',1000),repeat('a',1000),repeat('a',1000),repeat('a',1000),
    -> repeat('a',1000),repeat('a',1000),repeat('a',1000),repeat('a',1000),repeat('a',1000));
Query OK, 1 row affected (0.03 sec)

-- t2 多于十个列
MySQL [testdb]> create table t2(
    -> id int primary key
    -> , col1 blob
    -> , col2 blob
    -> , col3 blob
    -> , col4 blob
    -> , col5 blob
    -> , col6 blob
    -> , col7 blob
    -> , col8 blob
    -> , col9 blob
    -> , col10 blob
    -> , col11 blob) charset=utf8 row_format=compact;
Query OK, 0 rows affected (0.04 sec)

MySQL [testdb]> insert into t2 values (1,
    -> repeat('a',767),repeat('a',767),repeat('a',767),repeat('a',767),repeat('a',767),
    -> repeat('a',767),repeat('a',767),repeat('a',767),repeat('a',767),repeat('a',767),
    -> repeat('a',767));
ERROR 1118 (42000): Row size too large (> 8126). Changing some columns to TEXT or BLOB or using ROW_FORMAT=DYNAMIC or ROW_FORMAT=COMPRESSED may help. In current row format, BLOB prefix of 768 bytes is stored inline.

-- 超过了,所以要将总和小于 8126
MySQL [testdb]> insert into t2 values (1, repeat('a',734), repeat('a',734), repeat('a',734), repeat('a',734), repeat('a',734), repeat('a',734), repeat('a',735), repeat('a',735), repeat('a',735), repeat('a',735), repeat('a',735));
Query OK, 1 row affected (0.03 sec)

-- 这时候已经达到了极限的状态,当我们再加列时,已经无法再扩展了。
[MySQL [testdb]> alter table t2 add column add_col1 varchar(10) not null default 'a';
ERROR 1118 (42000): Row size too large. The maximum row size for the used table type, not counting BLOBs, is 8126. This includes storage overhead, check the manual. You have to change some columns to TEXT or BLOBs

-- 修改表的 行类型
MySQL [testdb]> alter table t2 row_format= dynamic;
Query OK, 0 rows affected (0.07 sec)
Records: 0  Duplicates: 0  Warnings: 0

MySQL [testdb]> alter table t2 add column add_col1 varchar(10) not null default 'a';
Query OK, 0 rows affected (0.07 sec)
Records: 0  Duplicates: 0  Warnings: 0

你可能感兴趣的:(MySQL)