mysql 導入SQL文件報錯, Specified key was too long; max key length is 767 bytes

----MySQL導入數據的時候,老是報錯,本地測試都沒辦法測試---- 導出SQL文件正常, 在導入SQL文件的時候, 報錯-----大部分數據表導入成功, 個別的失敗html

         在網上看到不少建議: mysql

  1. 建議別直接運行sql文件,你能夠嘗試打開sql文件本身選取sql執行
  2. Navicat運行SQL文件時, 去掉第二個√(每一個運行中運行多重查詢這個選項去掉√)
  3. 確認下字段類型跟內容是否一致,主鍵是否重複插入?能夠單獨執行出錯的語句看下報錯提示
  4. SQL文件分批次執行, 排查哪裏出問題了.

         我看了一下個人兩個數據庫的版本, 線上的MySQL是5.7.24, 本地的MySQL是5.5.53, 不過我感受版本應該沒什麼問題, 由於5.5已經支持utfmb4編碼了. 我這裏導入失敗的緣由也不是版本的問題(我的感受). 記錄一下解決的過程:sql

  1. 按照上面第二個建議, 去掉Navicat第二個√, 大部分能夠導入成功, 而後檢查有那些導入失敗的. 我是用瀏覽器運行項目,根據項目報錯 而後看那些數據表不存在, 來肯定有哪些數據表沒導入成功. 
    Base table or view not found: 1146 Table 'txsj_fdqs.hjmallind_goods' doesn't exist The SQL being executed was: SELECT (case when g.cat_id=0 then c2.name else c.name end) name FROM `hjmallind_goods` `g` LEFT JOIN `hjmallind_cat` `c` ON c.id=g.cat_id LEFT JOIN `hjmallind_goods_cat` `gc` ON gc.goods_id=g.id LEFT JOIN `hjmallind_cat` `c2` ON gc.cat_id=c2.id WHERE ((`g`.`store_id`=5) AND (`g`.`is_delete`=0) AND (`g`.`mch_id`=0)) AND (`g`.`type`=0) AND (((`gc`.`is_delete`=0) AND (`gc`.`store_id`=5)) OR (isnull(gc.id))) GROUP BY `name` ORDER BY `g`.`cat_id`
  2. 說明數據庫剛剛沒有導入成功這張表, 那麼如今單獨導入這張表,  報錯:   Specified key was too long; max key length is 767 bytes  ,針對這個問題, 又上網查了半天, 解決辦法是, 打開這個表的SQL文件, 修改了聯合主鍵, 把varchar(255)改爲了varchar(60). 導入成功.
  3. 新的問題: 是什麼致使的上面的問題呢? 
    1. 猜想是編碼問題, 由於utf8mb4編碼是4字節的, 4×255>757 , 可是我去查看導入成功的表, 發現對應的字段也是utf8mb4編碼. 那應該就不是編碼致使的問題了.(由於這兩個版本的都支持utf8mb4,怎麼說也不該該是編碼問題吧.)
    2. 猜想多是本地PHPstudy默認設置了禁用innodb_large_prefix , 而後致使索引鍵前綴限制爲767字節 (須要去研究一下) .若是禁用innodb_large_prefix,不論是什麼表,索引鍵前綴限制爲767字節。----參考
  4. 新建mysql庫或者表的時候還有一個排序規則: (以前一直沒去想)
    utf8_unicode_ci比較準確,utf8_general_ci速度比較快。一般狀況下 utf8_general_ci的準確性就夠咱們用的了, 若是是utf8mb4那麼對應的就是 utf8mb4_general_ci utf8mb4_unicode_ci
  5. utf8和utf8mb4的區別: mb4就是most bytes 4的意思,專門用來兼容四字節的unicode. utf8mb4是utf8的超集,除了將編碼改成utf8mb4外不須要作其餘轉換, 固然,爲了節省空間,通常狀況下使用utf8也就夠了.  原來mysql支持的 utf8 編碼最大字符長度爲 3 字節,若是遇到 4 字節的寬字符就會插入異常了.
  6.        系統變量innodb_large_prefix開啓了,則對於使用DYNAMIC或COMPRESSED行格式的InnoDB表,索引鍵前綴限制爲3072字節。若是禁用innodb_large_prefix,不論是什麼表,索引鍵前綴限制爲767字節。數據庫

           上述的bug很明顯是索引超出了限制的長度767(我司生產上innodb_large_prefix禁用了):瀏覽器

           我發現報錯的那張表創建了一個varchar類型的索引,varchar(255),以爲沒什麼問題,其實否則,上述的767是字節,而varchar類型是字符,同時我發現我使用的字符集爲(utf8mb4),這個指每一個字符最大的字節數爲4,因此很明顯 4*255 > 767less

    因此就報上述錯了(Specified key was too long; max key length is 767 bytes)。ide

           解決方法:測試

           改變varchar的字符數,我改爲了64就能夠了。varchar(64)ui

           或者啓用innodb_large_prefix,那麼限制值會增長到3072            ----------------------------https://blog.csdn.net/chenjianhuideyueding/article/details/88426021編碼

  7. 終於找到了緣由, 去本地MySQL查看是否開啓了innodb_large_prefix, 這個參數是限制索引列長度
    show variables like 'innodb_large_prefix';         //查看是否開啓innodb_large_prefix 的命令

    發現本地的MySQL默認是沒有開啓的. 線上的是開啓了的(不過不知道是以前有人開啓的, 仍是5.7版本默認開啓的. 應該是默認開啓的! 反正不用管這些~無所謂) 每一個人的MySQL配置不一樣, 要看具體什麼狀況了.....

  8. 關於如何開啓innodb_large_prefix,解決方案也在這裏:  可參考http://www.javashuo.com/article/p-straedam-m.html
  9. mysql uses 1 or 2 extra bytes to record the values length: 1 byte if the column's max length is 255 bytes or less, 2 if it's longer than 255 bytes. the utf8_general_ci encoding needs 3 bytes per character so varchar(20) uses 61 bytes, varchar(500) uses 1502 bytes in total 1563 bytes。引自--https://stackoverflow.com/questions/1814532/1071-specified-key-was-too-long-max-key-length-is-767-bytes
相關文章
相關標籤/搜索