關於建立索引的 767 bytes 長度限制

ealiwood發表於2018-03-28

生產環境執行

php artisan migrate 

Laravel 丟擲錯誤:

Index column size too large. The maximum column size is 767 bytes.

然而在本地開發的時候是正常的。

搜尋了一番。 原因定位在欄位的長度設定

  • Laravel 建表使用的是 utf8mb4 字符集。 這個一個4位元組字符集
  • 如果說最大限制是 767 bytes。 那麼一個 varchar 欄位:767/4=191.75。
  • 所以我欄位設定使用預設的(255),遠遠超出了限制。

為什麼在本地開發時又正常呢?

  • 本地開發使用的 MySQL5.7 而線上環境是 MySQL5.6。
  • MySQL5.7 有預設引數 innodb_default_row_format=dynamicinnodb_large_prefix=on。這樣的引數下是允許建立長位元組索引的。
  • MySQL5.6 的引數 innodb_large_prefix 預設為 off ,並且沒有一個預設引數可以在新建表時選擇自己想要的 row_format,只能在 create tablealert table 時 加上 ROW_FORMAT=DYNAMIC

目前我試過可行的三種方法

  1. 將建立索引的 varchar 欄位長度調低,使所有欄位位元組之和不超過 767 bytes。
  2. 建表時將 MySQL 的 charset 改為 utf8 ,collation 改為 utf8_general_ci。可在 config/database.php 中設定預設值。
  3. 將 MySQL 升級到 5.7 版本

未嘗試的方法

  1. 設定 MySQL 的引數:set GLOBAL innodb_large_prefix=ON;
  2. 建表時新增 ROW_FORMAT=DYNAMIC

參考

MySQL 5.6 Reference Manual : DYNAMIC and COMPRESSED Row Formats
MySQL 5.7 Reference Manual : Limits on InnoDB Tables

相關文章