AdonisJS v4执行migration:run报错:添加.unique()触发键过长问题
解决Migration执行时"Specified key was too long; max key length is 767 bytes"报错(仅添加unique约束时触发)
这个问题我帮不少开发者排查过,核心原因是MySQL InnoDB引擎的索引长度限制——默认情况下,InnoDB的单列索引最大支持767字节。如果你用的是utf8mb4字符集(现在大部分项目都会用这个来支持emoji),每个字符最多占4字节,那算下来单列索引的字符长度上限就是767/4≈191个字符。当你给超过191字符的字段加unique约束时,就会触发这个报错。
下面给你几个实用的解决方案,你可以根据自己的业务场景选:
方案1:缩短unique约束字段的长度(最简单直接)
如果业务上允许,直接把字段长度调整到191以内就行。比如原来定义的varchar(255)改成varchar(191),这样191×4=764字节,刚好卡在767的限制内。举个TypeORM migration的例子(其他ORM写法类似):
await queryRunner.changeColumn( 'user', 'email', new TableColumn({ name: 'email', type: 'varchar', length: '191', // 调整为191 isUnique: true, isNullable: false }) );
方案2:开启MySQL的大索引前缀支持
如果不想缩短字段长度,可以修改MySQL配置来放宽索引长度限制。这个需要满足几个前提:表必须是InnoDB引擎、用utf8mb4字符集,并且表的行格式是DYNAMIC或COMPRESSED。
步骤如下:
- 找到MySQL的配置文件(Linux是
/etc/my.cnf或/etc/mysql/my.cnf,Windows是my.ini),添加或修改以下配置:
[mysqld] innodb_large_prefix = on innodb_file_format = Barracuda innodb_file_per_table = on
- 重启MySQL服务,让配置生效
- 在你的migration里,确保表使用DYNAMIC行格式:
await queryRunner.createTable( new Table({ name: 'user', columns: [ // 你的字段定义 { name: 'long_unique_field', type: 'varchar', length: '255', isUnique: true } ], options: { engine: 'InnoDB', charset: 'utf8mb4', collate: 'utf8mb4_unicode_ci', rowFormat: 'DYNAMIC' // 指定行格式 } }) );
方案3:创建前缀unique索引
如果上面两种方案都不适合,可以给字段的前N个字符创建unique约束。比如取字段的前100个字符作为unique索引,这样索引长度就会控制在100×4=400字节以内,远低于767的限制。
用SQL直接写的话:
ALTER TABLE your_table ADD UNIQUE KEY idx_unique_long_field (long_unique_field(100));
在TypeORM里的写法:
await queryRunner.createIndex( 'your_table', new TableIndex({ name: 'idx_unique_long_field', columnNames: ['long_unique_field(100)'], // 指定前缀长度 isUnique: true }) );
⚠️ 注意:这种方式可能会有极小概率出现不同内容但前缀相同的冲突,需要结合你的业务场景判断是否可以接受。
内容的提问来源于stack exchange,提问作者Emad Fani
相关产品推荐
相关产品推荐

