django.db.utils.OperationalError:(1071,'指定密钥太长;最大密钥长度为767字节')

时间:2015-04-21 20:06:33

标签: python django database mariadb migrate

我的模特:

class Course(models.Model):
    language = models.ForeignKey(Language)
    name = models.CharField(max_length=50, unique=True, default='course')
    title = models.CharField(max_length=1024, default='no title')
    foreign_title = models.CharField(max_length=1024, default='no title', blank=True)
    header = models.CharField(max_length=1024, default='', blank=True)
    description = models.TextField(null=True, blank=True)

    def __str__(self):
        return self.title

    def __unicode__(self):
        return u'%s' % self.title

我添加“unique_together”:

class Course(models.Model):
    language = models.ForeignKey(Language)
    name = models.CharField(max_length=50, unique=True, default='course')
    title = models.CharField(max_length=1024, default='no title')
    foreign_title = models.CharField(max_length=1024, default='no title', blank=True)
    header = models.CharField(max_length=1024, default='', blank=True)
    description = models.TextField(null=True, blank=True)

    class Meta:
        unique_together = ['language', 'name', 'title']

    def __str__(self):
        return self.title

    def __unicode__(self):
        return u'%s' % self.title

获取错误的迁移时间:

 django.db.utils.OperationalError: (1071, 'Specified key was too long; max key length is 767 bytes')

我的数据库是:     mysql Ver 15.1使用readline 5.2分发10.0.17-MariaDB,用于debian-linux-gnu(x86_64)

我试图增加索引mysql的长度:

MariaDB [(none)]> set global innodb_file_format = BARRACUDA;
Query OK, 0 rows affected (0.00 sec)

MariaDB [(none)]> set global innodb_large_prefix = ON;
Query OK, 0 rows affected (0.00 sec)

但这仍然不够:

django.db.utils.OperationalError: (1071, 'Specified key was too long; max key length is 3072 bytes')

问题索引长度。如何指定Django索引的长度限制?

8 个答案:

答案 0 :(得分:24)

解决方案

ALTER DATABASE `databasename` CHARACTER SET utf8; 

答案 1 :(得分:3)

前两个答案在我的情况下没有帮助,所以当你的限制是1000时,我将我的解决方案发布到我的案例中(即1071,'指定密钥太长;最大密钥长度为1000字节“)。

首先,请确保您正在进行utf8编码!

然后,导航到您的设置文件my.ini,找到行default-storage-engine=xxx。如果是

default-storage-engine=MYISAM

请转到

default-storage-engine=InnoDB

然后,问题应该解决。

原因很简单,因为MYISAM不支持大于1000字节的密钥大小。

答案 2 :(得分:1)

我认为所有这四件事都是必需的:

SET GLOBAL innodb_file_per_table = ON,
           innodb_file_format = Barracuda,
           innodb_large_prefix = ON;
CREATE/ALTER TABLE ...
    ROW_FORMAT = DYNAMIC or COMPRESSED

这应该超过一列的767字节限制,但不会超过整个索引的3072字节限制。

为了使由字符串组成的复合唯一索引,请对某些字符串进行规范化。用4字节的INT替换长字符串会使索引缩小到限制以下。

答案 3 :(得分:0)

您可以重新创建"数据库"再次:

CREATE DATABASE mydatabase CHARACTER SET utf8 DEFAULT COLLATE utf8_general_ci;

或更改配置文件。打开/etc/mysql/mariadb.conf.d/50-server.cnf并更改:

character-set-server  = utf8
collation-server      = utf8_general_ci

答案 4 :(得分:0)

只需将数据库升级并迁移到 MySQL-8.0.11 或** MySQL-5.7.21 **,还请确保使用 utf8 utf8_general_ci < / em>

我遇到了问题,然后在测试环境中将其更新为8.0.11,在服务器上将其更新为5.7.21。现在,它可以在两种环境中迁移。

答案 5 :(得分:0)

将mysql升级到5.7,然后尝试再次迁移。

wget https://dev.mysql.com/get/mysql-apt-config_0.8.1-1_all.deb  
sudo dpkg -i mysql-apt-config_0.8.1-1_all.deb  
sudo apt-get update
sudo apt-get install mysql-server

答案 6 :(得分:0)

我最终添加了

'OPTIONS': { 'init_command': 'SET storage_engine=INNODB;' }

设置为我的数据库支持的settings.py中的配置,此问题已解决。

MySQL服务器被配置为使用InnoDB作为默认引擎,但是由于某些原因,它仍然尝试使用MyISAM创建表。我正在将MySQL 5.1与Django 2.2.1和Python 3.6.7一起运行

答案 7 :(得分:0)

由于这是此类错误的热门帖子之一,因此我可以分享在将 S3 路径存储到我的数据库时对我有用的解决方案。

我正在向所需字段添加 MySQL prefix 索引。

# my_app/models.py
class File(models.Model):
    s3_path = models.CharField(max_length=1024, help_text="S3 object key")


# my_app/migration_000x.py
from django.db import migrations

class Migration(migrations.Migration):

    dependencies = [
        (...),
    ]

    operations = [
        migrations.RunSQL(
            sql="CREATE INDEX my_app_file_s3_path__prefix ON my_app_file (s3_path(768));",
            reverse_sql="DROP INDEX my_app_file_s3_path__prefix ON my_app_file;",
        )
    ]

我可以避免这种情况,因为我知道大多数条目都很短(100-200 个字符),因此即使仅使用前缀索引它们也会受益,但我仍然保留 max_length我通过 AWS S3。

我的所有表都使用 InnoDB 引擎和 utf8mb4_unicode_ci