MySQL 异常:max key length is 767 bytes

文若10个月前技术文章186

前言

最近迁移几张表,又遇到 767 异常,迁移前只检查了 sql_mode 忽略对比了这个参数,导致几张表创建失败,其实解决方法也很简单,开启 innodb_large_prefix 参数重新导入即可。该 ERROR 常发生在字符串类型的大字段上,本篇文章简单记录下该问题。

42000 Specified key was too long; max key length is 767 bytes

1. 767 bytes 解读

如何知道某张表字符串字段占多少 bytes 呢?需要结合表的字符集来看:

CREATE TABLE `test_index` (
 `id` bigint(20) NOT NULL AUTO_INCREMENT,
 `name` varchar(800) DEFAULT NULL,
 PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

上表的字符类型是 utf8 我们可以通过查表来判断字符最大可占用的空间:

show character set;

CharsetDescriptionDefault collationMaxlen
big5Big5 Traditional Chinesebig5_chinese_ci2
dec8DEC West Europeandec8_swedish_ci1
cp850DOS West Europeancp850_general_ci1
hp8HP West Europeanhp8_english_ci1
koi8rKOI8-R Relcom Russiankoi8r_general_ci1
latin1cp1252 West Europeanlatin1_swedish_ci1
latin2ISO 8859-2 Central Europeanlatin2_general_ci1
swe77bit Swedishswe7_swedish_ci1
asciiUS ASCIIascii_general_ci1
ujisEUC-JP Japaneseujis_japanese_ci3
sjisShift-JIS Japanesesjis_japanese_ci2
hebrewISO 8859-8 Hebrewhebrew_general_ci1
tis620TIS620 Thaitis620_thai_ci1
euckrEUC-KR Koreaneuckr_korean_ci2
koi8uKOI8-U Ukrainiankoi8u_general_ci1
gb2312GB2312 Simplified Chinesegb2312_chinese_ci2
greekISO 8859-7 Greekgreek_general_ci1
cp1250Windows Central Europeancp1250_general_ci1
gbkGBK Simplified Chinesegbk_chinese_ci2
latin5ISO 8859-9 Turkishlatin5_turkish_ci1
armscii8ARMSCII-8 Armenianarmscii8_general_ci1
utf8UTF-8 Unicodeutf8_general_ci3
ucs2UCS-2 Unicodeucs2_general_ci2
cp866DOS Russiancp866_general_ci1
keybcs2DOS Kamenicky Czech-Slovakkeybcs2_general_ci1
macceMac Central Europeanmacce_general_ci1
macromanMac West Europeanmacroman_general_ci1
cp852DOS Central Europeancp852_general_ci1
latin7ISO 8859-13 Balticlatin7_general_ci1
utf8mb4UTF-8 Unicodeutf8mb4_general_ci4
cp1251Windows Cyrilliccp1251_general_ci1
utf16UTF-16 Unicodeutf16_general_ci4
utf16leUTF-16LE Unicodeutf16le_general_ci4
cp1256Windows Arabiccp1256_general_ci1
cp1257Windows Balticcp1257_general_ci1
utf32UTF-32 Unicodeutf32_general_ci4
binaryBinary pseudo charsetbinary1
geostd8GEOSTD8 Georgiangeostd8_general_ci1
cp932SJIS for Windows Japanesecp932_japanese_ci2
eucjpmsUJIS for Windows Japaneseeucjpms_japanese_ci3
gb18030China National Standard GB18030gb18030_chinese_ci4

例如 utf8 的 Maxlen = 3 表示一个字符最大占用 3 bytes。那么 varchar 类型小于 255 字符,就不会触发 767 异常。

2. 异常原因

为什么会有这个异常呢?其实该异常属于 MySQL Innodb 引擎的限制,例如一张表最多有 1017 个字段,一张表最大有 64 个二级索引一样,如果索引列的字符长度很大的话,二级索引占用的空间也会非常大,一个页面存储的索引字段减少,索引深度会更容易变深,增加 IO 次数,搜索的性能也不会理想。

If innodb_large_prefix is enabled (the default), the index key prefix limit is 3072 bytes for InnoDB tables that use the DYNAMIC or COMPRESSED row format. If innodb_large_prefix is disabled, the index key prefix limit is 767 bytes for tables of any row format.

Innodb 引擎的限制:14.23 InnoDB Limits  

3. 5.7 和 8.0 版本的区别

在 5.7 版本中,对于使用 DYNAMIC 或 COMPRESSED 行格式的 InnoDB 表,索引前缀的限制为 767 bytes,如果开启 innodb_large_prefix 参数,限制阈值上调为 3072 bytes。

在 8.0 版本中,参数 innodb_large_prefix 被删除,索引前缀最大为 3072 bytes 不再有 767 bytes 的限制。

ERROR 1071 (42000): Specified key was too long; max key length is 3072 bytes


相关文章

MySQL运维实战(4.3) SQL_MODE之ONLY_FULL_GROUP_BY

设置ONLY_FULL_GROUP_BY后,对有group by子句SQL,select的字段要么是group by中的字段,要么对字段进行聚合运算,否则sql执行报错。不设置ONLY_FULL_GR...

Java-API对HDFS的操作(IDEA版)

Java-API对HDFS的操作(IDEA版)

前期工作首先就是安装maven在win系统下不配置hadoop环境,直接运行代码会报错,显示缺少winutils.exe 和 hadoop.dll 两个文件首先添加pom.xml文件  <dep...

开源大数据集群部署(十四)Ranger集成Hbase

开源大数据集群部署(十四)Ranger集成Hbase

在hd1.dtstack.com主机上执行在hmaster和back master上进行安装和执行Ø 解压ranger-2.3.0-hbase-plugin[root@hd1.dtstack.com ...

LINUX 安全运维-OpenSSH安全

LINUX 安全运维-OpenSSH安全

SSH 是建立在应用层基础上的安全协议,是目前较可靠,专为远程登录会话和其他网络服务提供安全性的协议。利用 SSH协议可以有效防止远程管理过程中的信息泄露问题。SSH最初是UNIX系统上的一...

静默安装oracle11g单实例

环境: CentOS 7.8 11.2.0.4.0 orclp:172.16.104.31一、准备1、依赖包检查pdksh 在 redhat 上叫 ksh检查是否有安装root# rpm -q bin...

MySQL 小数类型介绍

MySQL 小数类型介绍

前言对于保证精度的数字,MySQL 也有对应的小数类型,下图是 MySQL 中小数类型概览。 浮点:小数点非固定的数,可表示数据范围较广,整数,小数都可表示。定点:小数点固定,可表示整数,小数。int...

发表评论    

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。