【问题标题】:Django's syncdb fails with MySQL errno: 150Django 的同步数据库因 MySQL 错误而失败:150
【发布时间】:2011-11-14 01:21:41
【问题描述】:

首先,这是我目前的设置:

Django:1.3 版

MySQL:4.0.18 版(不是我的第一选择...)

当我运行 syncdb 时,我收到以下错误:

Creating tables ...
Creating table auth_permission
Creating table auth_group_permissions
Traceback (most recent call last):
  File "C:\path_to_app\manage.py", line 14, in <module>
    execute_manager(settings)
  File "C:\Python27\lib\site-packages\django\core\management\__init__.py", line 438, in execute_manager
    utility.execute()
  File "C:\Python27\lib\site-packages\django\core\management\__init__.py", line 379, in execute
    self.fetch_command(subcommand).run_from_argv(self.argv)
  File "C:\Python27\lib\site-packages\django\core\management\base.py", line 191, in run_from_argv
    self.execute(*args, **options.__dict__)
  File "C:\Python27\lib\site-packages\django\core\management\base.py", line 220, in execute
    output = self.handle(*args, **options)
  File "C:\Python27\lib\site-packages\django\core\management\base.py", line 351, in handle
    return self.handle_noargs(**options)
  File "C:\Python27\lib\site-packages\django\core\management\commands\syncdb.py", line 101, in handle_noargs
    cursor.execute(statement)
  File "C:\Python27\lib\site-packages\django\db\backends\util.py", line 34, in execute
    return self.cursor.execute(sql, params)
  File "C:\Python27\lib\site-packages\django\db\backends\mysql\base.py", line 86, in execute
    return self.cursor.execute(query, args)
  File "C:\Python27\lib\site-packages\MySQLdb\cursors.py", line 174, in execute
    self.errorhandler(self, exc, value)
  File "C:\Python27\lib\site-packages\MySQLdb\connections.py", line 36, in defaulterrorhandler
    raise errorclass, errorvalue
_mysql_exceptions.OperationalError: (1005, "Can't create table '.\\database_name\\#sql-d64_e75f2.frm' (errno: 150)")

据我了解,这与 InnoDB 如何处理外键有关。这是我的设置文件的样子:

DATABASES = {
    'default': {
        ....
        'OPTIONS':  { 'init_command': 'SET table_type=INNODB;', 'charset': 'latin1'}, 
    },
}

当未指定“SET table_type=INNODB”时,一切运行顺利。我在网上四处查看,似乎 InnoDB 引擎不喜欢 the SQL Django is generating

目前,我发现的唯一解决方法是自己创建表,并使用 inspectDB 生成模型...

有解决办法吗?谢谢!

【问题讨论】:

    标签: python mysql django


    【解决方案1】:

    使用 Django 1.5,错误是 mysql 使用 Innodb 作为默认引擎创建表。解决方案是将以下内容添加到数据库的设置中,这会产生约束问题:

    DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'etc....',
        'OPTIONS': {
               "init_command": "SET storage_engine=MyISAM",
        },
    },
    
    }
    

    【讨论】:

      【解决方案2】:

      MySQL docs 这么说:

      无法创建表。如果错误消息是指错误 150,则表 创建失败,因为外键约束不正确 形成。如果错误消息是指错误–1,则表创建 可能失败,因为该表包含匹配的列名 内部 InnoDB 表的名称。

      在此处发布您的模型代码,让我们看看可能出了什么问题。如果你不能,也不知道出了什么问题,请尝试平分存储库修订,或平分应用程序:关闭一半的应用程序,看看它是否正确同步,然后平分包含错误模型的部分,等等。

      【讨论】:

      • 感谢 culebrón 的回答!但是,我的模型在这里没有引起问题。正如您在堆栈跟踪中看到的,syncdb 在创建 django auth 表时失败。即使使用最基本的模型,脚本也会失败。
      【解决方案3】:

      最近我也遇到了这个错误。 就我而言,发生此错误是因为与您要创建的表相比,包含外键的表使用不同的引擎。 解决此问题的一种懒惰方法是使用以下方法统一这两个表的引擎:

      ALTER TABLE table_name ENGINE = engine_type;
      

      它对我有用。

      【讨论】:

        【解决方案4】:

        我追踪了问题的根源。当创建 2 个具有外键关系的 InnoDB 表时,外键列必须显式索引prior to MySQL 4.1.2。使用 Django 的 ORM,这可以通过在外键字段中使用 db_index=True 选项来完成。但是,在 Django 生成的 SQL 中,CREATE INDEX 语句是在创建外键关系后发出的。例如,对于以下模型:

        class Customer(models.Model):
            first_name = models.CharField(max_length=100)
            last_name = models.CharField(max_length=100)
        
        class Order(models.Model):
            customer = models.ForeignKey(Customer, db_index=True)
        

        Django 生成以下 SQL 代码:

        BEGIN;
        CREATE TABLE `foo_app_customer` (
            `id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY,
            `first_name` varchar(100) NOT NULL,
            `last_name` varchar(100) NOT NULL
        )
        ;
        CREATE TABLE `foo_app_order` (
            `id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY,
            `customer_id` integer NOT NULL
        )
        ;
        ALTER TABLE `foo_app_order` ADD CONSTRAINT `customer_id_refs_id_27e4f922` FOREIGN KEY (`customer_id`) REFERENCES `foo_app_customer` (`id`);
        CREATE INDEX `foo_app_order_12366e04` ON `foo_app_order` (`customer_id`);
        COMMIT;  
        

        如果您尝试使用 MySQL 4.0 运行此代码,则在尝试执行 ALTER TABLE 语句时会出现 errno 150。但是,如果首先发出 CREATE INDEX 声明,那么一切都会像魅力一样。据我所知,唯一的解决方法是手动创建自己的表,然后使用inspectdb 生成模型。

        另外,我创建了一个新的Django ticket

        【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-12-29
        • 1970-01-01
        • 2013-10-27
        • 1970-01-01
        • 2021-05-07
        • 2021-12-07
        相关资源
        最近更新 更多