我有一个表,其中包含大量的长文本字段(18),以及许多其他各种整数和varchar字段。最近,添加了许多其他的长文本字段,这些字段突然迫使我学习有关8K行大小限制的所有信息。该数据库正在运行Mysql 5.6.34,并且该表当前为Antelope / ROW_FORMAT = COMPACT。
我的理解是,以这种格式,每一列将占用每行768个字节,直到溢出到单独的存储中为止。当太多的各种长文本获取大量数据时,这导致我出现此错误:
行大小太大(> 8126)。将某些列更改为TEXT或BLOB或使用ROW_FORMAT = DYNAMIC或ROW_FORMAT = COMPRESSED可能会有所帮助。在当前行格式中,内联存储768个字节的BLOB前缀。忽略表中的其余字段,所有18个长文本均为768字节,那么主索引将为所有字段存储13,824字节。
我试图将表更新为ROW_FORMAT = DYNAMIC,期望这会将长文本的溢出阈值从768个字节降低到仅20个字节,因此应将所有长文本字段的最大主索引存储要求降低到18个* 20 = 360字节我尝试了以下更新:
ALTER TABLE mytable ROW_FORMAT=DYNAMIC;
OPTIMIZE TABLE mytable;
无错误,并显示以下输出:
mydb.mytable优化说明表不支持优化,而是进行重新创建+分析 mydb.mytable优化状态确定
如果查看该表的CREATE TABLE语法,我会看到已设置ROW_FORMAT = DYNAMIC。
然后,我试图写一行以填充所有长文本列,每个长约5.7kb,但是在阻止保存该行之前,我只能填充其中的10个,并且10 * 768 = 7,680字节,当考虑其他非长文本必填字段时,该值已接近8kb的限制,这表明ROW_FORMAT = DYNAMIC指令不适用于现有行。
我不是特别想通过转储/导入来重新创建数据库,因为它特别大,并且会延长服务停机时间,在其他选项用尽之前,我不确定是否可以证明其合理性。
答案 0 :(得分:1)
原来,我需要在ALTER / OPTIMIZE之前设置innodb_file_format=barracuda
。出于某种原因,我将设置DYNAMIC设置为隐含地设置梭子鱼作为福音,但是事实已不再如此:
SET GLOBAL innodb_file_format=barracuda
答案 1 :(得分:1)
(此答案虽然集中在索引上,但很可能可以解决您的 table 问题。)
http://mysql.rjweb.org/doc.php/limits#767_limit_in_innodb_indexes
处理767限制有5个选择。这似乎是您需要的那个
myGenerator
(升级到5.7.7或更高版本是另一种解决方案-但这仅将上述设置设为默认值;我认为您仍然需要执行 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)
。)
答案 2 :(得分:0)
这是MySQL的文档。要创建使用COMPRESSED或DYNAMIC Barracuda文件格式的表,
https://dev.mysql.com/doc/refman/5.6/en/innodb-parameters.html#sysvar_innodb_file_format