导入sql文件报错:1071 Specified key was too long; max key length is 767 bytes

一、背景
今天把服务器的数据库导出了一份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低
导入sql文件报错:1071 Specified key was too long; max key length is 767 bytes的更多相关文章
- mysql 导入SQL文件报错
----MySQL导入数据的时候,总是报错,本地测试都没办法测试---- 导出SQL文件正常, 在导入SQL文件的时候, 报错-----大部分数据表导入成功, 个别的失败 在网上看到很多建议: 建议别 ...
- 【MySQL篇】Navicat导入SQL文件报错终极解决方案
面对大数据库文件(一般50M以上),使用Navicat导入的时候容易出现[ERR]2006等报错问题,此文提供了几种办法,包括修改MySQL的配置参数在网上也有很多详细教程介绍过,但此文精彩处在于前面 ...
- mysql小知识点汇总---(时间与时间戳的转换, 修改mysql用户名密码, navicate 导入sql文件报错 1153)
1. 时间与时间戳的转换 1.1 时间戳转时间 FROM_UNIXTIME(add_time, '%Y-%m-%d') 1.2 时间转时间戳 UNIX_TIMESTAMP('2015-04-29') ...
- 导入json文件报错,TypeError expected string or buffer
导入json文件报错,TypeError expected string or buffer 原因:用字符串赋值后,python会把双引号转换为单引号 import json data = [{&qu ...
- 【SQLServer2008】之如何导入mdf,ldf文件、导入.mdf文件报错解决问题以及如何获得Authenticated Users 权限
一.如何导入mdf,ldf文件: 链接:http://jingyan.baidu.com/article/09ea3ede21258cc0afde3943.html 二.导入.mdf文件报错解决问题 ...
- MYSQL 编码方式 ------导入 .sql 文件 报编码错误
在做计量泵上位机时,利用MYSQL存储数据,建表hisruninfo(计量泵历史运行数据表). 表格式为utf8,查过数据库 格式 同样为utf8 导入该hisruninfo.sql文件时,并没有报错 ...
- mysql----------mysql5.7.11导入sql文件时报错This function has none of DETERMINISTIC, NO SQL, or READS SQL DATA in its declaration and binary logging is enabled
1.导入sql文件出现如下错误. [Err] 1418 - This function has none of DETERMINISTIC, NO SQL, or READS SQL DATA in ...
- SQL Server导入Excel文件报错
目录 文本被截断,或者一个或多个字符在目标代码页中没有匹配项 原因 解决方法 该值违反了该列的完整性约束 空行 没有设置为允许为NULL 我以前也导入过数据,也没报错,今天再次导入数据的时候,发现了两 ...
- MySQL导入较大sql文件报错max_allowed_packet
1.查看当前最大允许导入sql文件大小 show VARIABLES like '%max_allowed_packet%'; 2.修改方式 1.永久生效 修改my.cnf文件 vim /etc/my ...
随机推荐
- Python正则表达式指南 (转)
本文http://www.cnblogs.com/huxi/archive/2010/07/04/1771073.html 正则表达式经常被用到,而自己总是记不全,转载一份完整的以备不时之需. 1. ...
- java 泛型实现原理
泛型思想最早在C++语言的模板(Templates)中产生,Java后来也借用了这种思想.虽然思想一致,但是他们存在着本质性的不同. C++中的模板是真正意义上的泛型,在编译时就将不同模板类型参数编译 ...
- lsof根据端口返回进程号杀死进程的方法
参考自:http://newmiracle.cn/?p=661 Linux shell根据端口返回进程号杀死进程的方法 kill -9 `lsof -t -i:8888` 这个就是杀死8888端口的进 ...
- spring与activemq(三种消息监听方式)
1.3 消息监听器MessageListener 在Spring整合JMS的应用中我们在定义消息监听器的时候一共可以定义三种类型的消息监听器,分别是MessageListener.Sessio ...
- 阅读OReilly.Web.Scraping.with.Python.2015.6笔记---Crawl
阅读OReilly.Web.Scraping.with.Python.2015.6笔记---Crawl 1.函数调用它自身,这样就形成了一个循环,一环套一环: from urllib.request ...
- jquery.nicescroll.min.js滚动条使用方法
jquery.nicescroll.min.js滚动条使用方法,Nicescroll 是制作自定义滚动条的jq插件.支持div,iframe,html等使用,兼容IE7-8,safari,firefo ...
- sql中的STRFTIME
STRFTIME返回的是一个字符串 STRFTIME('%w',myTime) in ('1','2','4','5') 可以正确执行,而 STRFTIME('%w',myTime) in (1,2, ...
- 黄聪:PHP如何实现延迟一定时间后自动刷新当前页面、自动跳转header("refresh:1;url={$url}");
//1秒后自动跳转 header("refresh:1;url={$url}"); exit; //1秒后自动刷新当前页面header("refresh:1;" ...
- windows 下跟踪日志的几个工具总结
1.baretailpro.exe 2.wintail.exe 3.vim(using tail bundle plugin) 4.Notepad++ (Plugin->Plugin Manag ...
- django获取表单数据
django获取单表数据的三种方式 v1 = models.Business.objects.all() # v1是QuerySet的列表 ,内部元素都是对象 v2 = models.Business ...