3

我有一个包含大量长文本字段 (18) 以及许多其他各种整数和 varchar 字段的表。最近添加了一些额外的长文本字段,这突然迫使我了解所有关于 8K 行大小限制的信息。DB 运行的是 Mysql 5.6.34,当前有问题的表是 Antelope / ROW_FORMAT=COMPACT。

我的理解是,在这种格式下,每列每行最多占用 768 个字节,直到溢出到单独的存储中。当太多的各种长文本获得大量数据时,这会导致我出现此错误:

行大小太大 (> 8126)。将某些列更改为 TEXT 或 BLOB 或使用 ROW_FORMAT=DYNAMIC 或 ROW_FORMAT=COMPRESSED 可能会有所帮助。在当前行格式中,768 字节的 BLOB 前缀被内联存储。忽略表中的其余字段,都是 768 字节的 18 个长文本,那么主索引将为所有字段存储 13,824 字节。

我试图将表更新为 ROW_FORMAT=DYNAMIC,期望这会将长文本的溢出阈值从 768 字节降低到仅 20 字节,因此应该将所有长文本字段的最大主索引存储要求降低到 18 * 20 = 360 字节。我尝试了以下更新:

ALTER TABLE mytable ROW_FORMAT=DYNAMIC;
OPTIMIZE TABLE mytable;

没有错误和以下输出:

mydb.mytable 优化说明 表不支持优化,做 recreate + analyze 代替 mydb.mytable 优化状态 OK

如果我查看表的 CREATE TABLE 语法,我可以看到 ROW_FORMAT=DYNAMIC 已设置。

然后我尝试写一行来填充所有大约 5.7kb 的长文本列,但是在我阻止保存该行之前我只能填充其中的 10 个,并且 10 * 768 = 7,680 字节,当记账时对于其他非长文本必填字段非常接近 8kb 限制,这表明 ROW_FORMAT=DYNAMIC 指令不适用于现有行。

我并不特别希望通过转储/导入来重新创建数据库,但是因为它特别大并且会代表延长的服务停机时间,我不确定在其他选项用尽之前我是否可以证明这一点。

4

3 回答 3

5

(这个答案虽然侧重于索引,但可能会解决您的问题。)

http://mysql.rjweb.org/doc.php/limits#767_limit_in_innodb_indexes

处理 767 限制有 5 种选择。这个好像是你需要的

   SET GLOBAL innodb_file_format=Barracuda;
   SET GLOBAL innodb_file_per_table=1;
   SET GLOBAL innodb_large_prefix=1;
   logout & login (to get the global values);
   ALTER TABLE tbl ROW_FORMAT=DYNAMIC;  -- (or COMPRESSED)

(升级到 5.7.7 或更高版本是另一种解决方案——但这只会将上述内容设置为默认值;我认为您仍然需要执行ALTER.)

于 2018-07-09T22:52:37.993 回答
1

原来我需要innodb_file_format=barracuda在 ALTER/OPTIMIZE 之前设置。出于某种原因,我认为设置 DYNAMIC 也会隐式设置梭子鱼作为福音,但事实已不再如此:

SET GLOBAL innodb_file_format=barracuda
于 2018-07-09T19:26:25.170 回答
0

这是来自 MySQL 的文档。要创建使用压缩或动态梭子鱼文件格式的表,需要启用。

https://dev.mysql.com/doc/refman/5.6/en/innodb-parameters.html#sysvar_innodb_file_format

于 2018-12-04T03:32:07.487 回答