昨晚在执行migration db变更时,报了一个错误:
CREATE TABLE `xxxx_configs` (
`id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
`rules` VARCHAR(512) NOT NULL DEFAULT '' COMMENT '例如:gantts_setting_var1_var2,var1=workspace_id,var2=user_id,具体规
则在代码中设置',
`abc` VARCHAR(255) NOT NULL DEFAULT '' COMMENT 'xxx',
`def` int(11) NOT NULL DEFAULT 0 COMMENT,
`ghi` TINYINT UNSIGNED NOT NULL DEFAULT '0' COMMENT '0(未启用), 1(启用)',
PRIMARY KEY (`id`),
UNIQUE INDEX `rules` (`rules`)
)
COLLATE='utf8_general_ci'
ENGINE=InnoDB
;;
Reason: Specified key was too long; max key length is 767 bytes
分析:
对于报错信息“: Specified key was too long; max key length is 767 bytes”,其实意思就是“索引字段长度太长,超过了767bytes”。
mysql的varchar主键只支持不超过767个字节或者768/2=384个双字节 或者767/3=255个三字节的字段 而GBK是双字节的,UTF8是三字节的。
那么问题来了,为什么内网版库执行正常,但是SaaS版执行异常呢?
(1) 字符集设置不同?
第一个想法是查看两个库的字符集设置是不是不一样,果然内网库的字符集character_set_database=lantin1,而saas库的字符集character_set_database= utf8。这时候,我很天真的以为可能是因为建表的时候没有指定字符集,所以在导入测试库的时候默认使用utf-8字符集,导致Specified key was too long。所以就更改了saas库中默认的字符集,但是导入数据的时候依然还是报同样的错误。而且我在建表的语句中发现了,其实原来就已经指定了字符集,都是UTF8(CHARSET=UTF8),所以字符集设置不同并不是问题的症结所在。下面是用show variable_name like ‘%character_set%’的展示结果:
(2)存储引擎惹的祸?
我查了一下,内网的SQL语句和SaaS的SQL语句是一致的,同一条语句指定的engine是一样的,所以也并非是engine的锅
(3)Mysql版本的锅?
查了一圈资料,在MySQL 5.6及之前的版本,使用InnoDB作引擎的表的索引大小要小于767B,对于MyISAM的限制则是1000B。在MySQL5.7之后此限制扩展到了3027B
内网是5.7版本的SQL, SaaS版是 基于MariaDB 10.1.9设计(兼容Mysql 5.6) ,应该是Mysql 5.5的版本(Server version: 5.5.5-10.1.44-MariaDB)
(4)解决方法?
减少索引列的长度 将varchar(512) 改成 varchar(255)
参考文章:
https://cloud.tencent.com/developer/article/1005696
https://blog.csdn.net/weixin_36210698/article/details/81568230