pymysql.err.OperationalError: (1071, 'Specified key was too long; max key length is 767 bytes') 错误解析及解决方案

在使用Python开发Web应用程序时,经常会涉及到与数据库进行交互的操作。而MySQL作为一种常用的关系型数据库,很多开发者选择使用pymysql库来连接和操作MySQL数据库。

然而,在使用pymysql库时,有时候会遇到pymysql.err.OperationalError: (1071, 'Specified key was too long; max key length is 767 bytes')的错误。这个错误的原因是因为MySQL的索引长度有限制,而pymysql在创建索引时可能会超过这个限制。

错误解析

MySQL的索引长度限制是根据字符集和排序规则来决定的。对于UTF8字符集,每个字符占用3个字节的情况下,索引长度限制是767个字节。对于UTF8MB4字符集,每个字符占用4个字节的情况下,索引长度限制是255个字符,即1020个字节。

当我们使用pymysql创建表并设置索引时,如果表的某个字段的长度超过了MySQL的索引长度限制,就会出现上述错误。

示例代码如下:

import pymysql

# 连接到MySQL数据库
conn = pymysql.connect(host='localhost', user='root', password='123456', database='test')

# 创建一个游标对象
cursor = conn.cursor()

# 创建一个表
create_table_sql = '''
CREATE TABLE `users` (
    `id` int(11) NOT NULL AUTO_INCREMENT,
    `name` varchar(255) NOT NULL,
    `email` varchar(255) NOT NULL,
    PRIMARY KEY (`id`),
    UNIQUE KEY `email_idx` (`email`(100))
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
'''
cursor.execute(create_table_sql)

# 关闭游标和连接
cursor.close()
conn.close()

在上述代码中,我们创建了一个名为users的表,并为email字段创建了一个长度为100的索引。如果我们的MySQL数据库使用的字符集是UTF8MB4,那么上述代码是没有问题的。但如果我们的MySQL数据库使用的字符集是UTF8,那么就会报错。

解决方案

要解决这个问题,我们有两种方法可以选择:

方法一:修改MySQL的配置文件

  1. 打开MySQL的配置文件(通常是my.cnfmy.ini)。

  2. 找到[mysqld]段落,在该段落中添加以下配置:

    [mysqld]
    innodb_large_prefix=true
    innodb_file_format=barracuda
    innodb_file_per_table=true
    
  3. 重启MySQL服务。

修改MySQL的配置文件可以解决该问题,但这需要对MySQL的配置文件进行修改,并且重启MySQL服务。

方法二:调整字段长度或索引长度

如果我们不想修改MySQL的配置文件,又想继续使用UTF8字符集,那么我们可以通过调整字段长度或索引长度来解决问题。

在上述示例代码中,我们为email字段创建了一个长度为100的索引。如果我们将索引长度调整为较小的值,就可以避免出现上述错误。

示例代码如下:

import pymysql

# 连接到MySQL数据库
conn = pymysql.connect(host='localhost', user='root', password='123456', database='test')

# 创建一个游标对象
cursor = conn.cursor()

# 创建一个表
create_table_sql = '''
CREATE TABLE `users` (
    `id` int(11) NOT NULL AUTO_INCREMENT,
    `name` varchar(255) NOT NULL,
    `email` varchar(255) NOT NULL,
    PRIMARY KEY (`id`),
    UNIQUE KEY `email_idx` (`email`(50))
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
'''
cursor.execute(create_table_sql)

# 关闭游标和连接
cursor.close()
conn.close()

在上述代码中,我们将email字段的索引长度调整为50,这样就可以避免超过MySQL的索引长度限制。

总结

在使用pymysql操作MySQL数据库时,有时候会遇到pymysql.err.OperationalError: (1071, 'Specified key was too long; max key length is 767 bytes')的错误。这个错误是由于MySQL