将
mysql 数据库里某个
UNIQUE 唯一索引字段从
utf8 改为
utf8mb4 时提示
1071 - Specified key was too long; max key length is 767 bytes ,来看看这个错误的来原因。
来几个知识点
- 一个字符
latin1 占用 1 bytes , utf8 占用 3 bytes ,而 utf8mb4 占用 4 bytes ;
- 在
mysql5.6 以及以前的版本的 InnoDB 引擎的表限制索引最多占用 767 bytes ;而 MyISAM 的是最长 1000 bytes 。
- 从
mysql5.7 版本开始这个限制提升到 3072 bytes , UTF8 可以达到 VARCHAR(1024) ;
所以当你的唯一索引字段在
mysql5.6 或更早的版本时(引擎为
InnoDB ),
utf8mb4 字符串最长能到
VARCHAR(191) (191*4=764),
utf8 可以到
VARCHAR(255) (255*·3=765)。如果你从不指定长度直接使用
utf8mb4 字段做唯一索引,就会报
Specified key was too long; max key length is 767 bytes 错误,因为计算默认字符串默认长度时是255。
这个问题在
Laravel 中就有可能发生,为了存储
emoji 它默认使用
utf8mb4 ,如果你的mysql版本低于5.7,就需要手动配置数据迁移生成的字符串默认长度,在
AppServiceProvider中调用
Schema::defaultStringLength 方法来配置它 :
use Illuminate\Support\Facades\Schema;
/**
* 引导任何应用程序服务。
*
* @return void
*/
public function boot()
{
Schema::defaultStringLength(191);
}
参考:
- https://stackoverflow.com/questions/1814532/1071-specified-key-was-too-long-max-key-length-is-767-bytes
- https://laravel-china.org/topics/14723/the-latest-modification-plan-prompts-specified-key-was-too-long-to-solve-it