执行以下命令时:

ALTER TABLE `mytable` ADD UNIQUE (
`column1` ,
`column2`
);

我得到了这个错误信息:

#1071 - Specified key was too long; max key length is 767 bytes

columnn1和column2的信息:

column1 varchar(20) utf8_general_ci
column2  varchar(500) utf8_general_ci

我认为varchar(20)只需要21个字节,而varchar(500)只需要501个字节。所以总字节数是522,小于767。为什么我得到了错误消息?

#1071 - Specified key was too long; max key length is 767 bytes

当前回答

我在这个话题上做了一些搜索,最后得到了一些自定义更改

MySQL工作台6.3.7版本有图形界面

启动Workbench并选择连接。 转到管理或实例并选择选项文件。 如果Workbench要求您允许读取配置文件,然后按OK两次。 在中心位置的管理员选项文件窗口出现。 进入InnoDB选项卡,如果在General部分没有检查innodb_large_prefix。 设置innodb_default_row_format选项值为DYNAMIC。

对于6.3.7以下的版本,直接选项不可用,因此需要使用命令提示符

Start CMD as administrator. Go To director where mysql server is install Most of cases its at "C:\Program Files\MySQL\MySQL Server 5.7\bin" so command is "cd \" "cd Program Files\MySQL\MySQL Server 5.7\bin". Now Run command mysql -u userName -p databasescheema Now it asked for password of respective user. Provide password and enter into mysql prompt. We have to set some global settings enter the below commands one by one set global innodb_large_prefix=on; set global innodb_file_format=barracuda; set global innodb_file_per_table=true; Now at the last we have to alter the ROW_FORMAT of required table by default its COMPACT we have to set it to DYNAMIC. use following command alter table table_name ROW_FORMAT=DYNAMIC; Done

其他回答

对于这个问题,我自己的解决方案比降低表的VARCHAR大小更简单,也更安全。

情况:CentOS 7服务器运行Plesk Obsidian 18.0.37和MariaDB 5.5。我试图从运行MariaDB 10.1的服务器导入MySQL转储。

解决方案:从MariaDB 5.5升级到10.6。

这些步骤大致基于以下指南和以下指南:

mysqldump -u admin -p`cat /etc/psa/.psa.shadow` --all-databases --routines --triggers > /root/all-databases.sql systemctl stop mariadb cp -a /var/lib/mysql/ /var/lib/mysql_backup Configure MariaDB repositories according to the official guide Make sure you meet Plesk's minimum version requirements detailed here yum install MariaDB-client MariaDB-server MariaDB-compat MariaDB-shared systemctl start mariadb In my case, the server failed to start here with an error: "Can't start server: Bind on TCP/IP port. Got error: 22: Invalid argument". The fix was to replace bind-address as follows in /etc/my.cnf and re-run the command: [mysqld] # OLD (broken) #bind-address = ::ffff:127.0.0.1 # NEW bind-address = 127.0.0.1 MYSQL_PWD=`cat /etc/psa/.psa.shadow` mysql_upgrade -uadmin plesk sbin packagemng -sdf rm -f /etc/init.d/mysql systemctl daemon-reload

MySQL对字符串中每个字符的字节数假设最坏的情况。对于MySQL 'utf8'编码,每个字符是3个字节,因为该编码不允许字符超过U+FFFF。对于MySQL 'utf8mb4'编码,它是每个字符4字节,因为这是MySQL所谓的实际UTF-8。

因此,假设您使用'utf8',那么您的第一列将占用索引的60字节,第二列将占用索引的1500字节。

在导入文件中用utf8替换utf8mb4。

但请注意,utf8字符集已弃用,它不支持所有的Unicode字符,例如表情符号,所以如果这样做,您将失去对Unicode的完全支持。

我发现这个查询在检测哪些列的索引违反了最大长度方面很有用:

SELECT
  c.TABLE_NAME As TableName,
  c.COLUMN_NAME AS ColumnName,
  c.DATA_TYPE AS DataType,
  c.CHARACTER_MAXIMUM_LENGTH AS ColumnLength,
  s.INDEX_NAME AS IndexName
FROM information_schema.COLUMNS AS c
INNER JOIN information_schema.statistics AS s
  ON s.table_name = c.TABLE_NAME
 AND s.COLUMN_NAME = c.COLUMN_NAME 
WHERE c.TABLE_SCHEMA = DATABASE()
  AND c.CHARACTER_MAXIMUM_LENGTH > 191 
  AND c.DATA_TYPE IN ('char', 'varchar', 'text')

将抱怨索引字段的CHARSET更改为“latin1” 例如:ALTER TABLE tbl CHANGE myfield varchar(600) CHARACTER SET latin1 DEFAULT NULL Latin1为一个字符使用一个字节,而不是四个