1. 程式人生 > >匯入sql檔案報錯:1071 Specified key was too long; max key length is 767 bytes

匯入sql檔案報錯:1071 Specified key was too long; max key length is 767 bytes

 

2018年05月22日 15:53:58  閱讀數:1503  

一、背景

今天把伺服器的資料庫匯出了一份sql檔案,準備匯入到本地,但是在匯入的時候,報了個錯:

Syntax error or access violation: 1071 Specified key was too long; max key length is 767 bytes

這就很奇怪了,明明伺服器上都可以,憑什麼我這邊就報錯呢。

二、錯誤分析

1、錯誤部分的sql檔案

CREATE TABLE `model_has_permissions` (
  `permission_id` int(10) unsigned NOT NULL,
  `model_id` int(10) unsigned NOT NULL,
  `model_type` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
  PRIMARY KEY (`permission_id`,`model_id`,`model_type`),
  KEY `model_has_permissions_model_id_model_type_index` (`model_id`,`model_type`),

 

就是這個primary key部分報錯的。錯誤資訊的意思是,設定的鍵長超過了767 bytes。

2、這個767 bytes是什麼玩意?

答:
(1)
在mysql 5.5.3之前,mysql的InnoDB引擎,要求設定的主鍵長度不得超過767bytes。
mysql的MyIsam引擎的主鍵長度不得超過1000 bytes。

(2)
在mysql中,gbk字符集會佔用2個位元組。utf8字元會佔用3個位元組。
而且從mysql5.5.3之後的版本,mysql 開始支援utf8m4字元,代表著一個字元佔用4個位元組。

也就是說:

(255+10+10)*3 = 825  //在用utf8作為字符集的時候,超過了規定的767 bytes
(255+10+10)*2 = 550  //當該用gbk作為字符集的時候
(255+10+10)*4 = 1100  //當用utf8m4作為字符集的時候,也超標了

3、大致原因知道之後,檢視sql檔案

(1)、資料庫使用的InnoDB引擎
(2)、資料庫使用utf8m4作為字符集

三、解決辦法

1、修改字元長度

//根據上面的分析可以進行計算,我的主鍵長度不能超過192
768/4 = 192

但這樣很明顯是不符合的需求的,不能隨便改動資料庫的欄位!

2、升級mysql

這個方案是在查詢伺服器資料庫版本的時候,發現伺服器資料庫採用的是mysql5.7版本。。也就是說在升級資料庫之後,是完全可以達到的。。

後面再查詢中發現一個國外的帖子:
連結:
https://stackoverflow.com/questions/1814532/1071-specified-key-was-too-long-max-key-length-is-767-bytes

原文:

767 bytes is the stated prefix limitation for InnoDB tables in MySQL version 5.6 (and prior versions). It's 1,000 bytes long for MyISAM tables. In MySQL version 5.7 and upwards this limit has been increased to 3072 bytes.
  • 1

原文的意思是說,在mysql的5.5.3版本之前,InnoDB引擎的主鍵對應的最大位元組數是767位元組,MyISAM對應的主鍵最大位元組是1000位元組。但是在mysql5.7版本之後,最大主鍵位元組增大為3072位元組。

OK,這樣就很明顯了,升級mysql是最佳的選擇。用整合環境的小夥伴可以關閉整合環境中的mysql,然後下載最新的mysql版本即可。

四、在解決問題時,學到的東西

1、檢視資料庫的儲存引擎

//進入資料庫,執行這個命令
show variables like '%storage_engine%';

2、檢視當前資料庫的字元編碼

show variables like '%character_set%';
  • 1

3、檢視資料庫的版本號

//進入資料庫之後,執行status即可
mysql>status

4、關於varchar

MySQL5.0.3之前varchar(n)這裡的n表示位元組數

MySQL5.0.3之後varchar(n)這裡的n表示字元數,比如varchar(200),不管是英文還是中文都可以存放200個

5、關於用varchar作為主鍵,不好的地方

      varchar相對於int來說佔用磁碟空間多,磁碟io也會多,然後記憶體頻寬也會多。這點上尤其在innodb更為明顯,innodb表的Secondary index的 leaf page中都要儲存primary key的值,主鍵如果是varchar,會導致secondary index的體積會比較大。而且varchar主鍵在比較上也會慢一些,插入時容易傳送資料的非順序插入,導致碎片,index tree效率比int低