Django的syncdb因MySQL errno:150而失败

时间:2011-09-09 19:27:57

标签: python mysql django

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

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生成模型......

有解决方法吗?谢谢!

4 个答案:

答案 0 :(得分:15)

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

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

}

答案 1 :(得分:4)

MySQL docs这样说:

  

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

在这里发布您的型号代码,让我们看看哪些是错的。如果您不能,并且不知道什么是错的,请尝试平分存储库修订或​​平分应用程序:关闭一半应用程序,查看它是否正确同步,然后将包含错误模型的部分一分为二,依此类推。

答案 2 :(得分:3)

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

ALTER TABLE table_name ENGINE = engine_type;

它对我有用。

答案 3 :(得分:0)

我追查了问题的根源。在创建具有外键关系的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语句时将发生错误150。但如果首先发布CREATE INDEX语句,一切都像魅力一样。据我所知,唯一的解决方法是手动创建自己的表,然后使用inspectdb生成模型。

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