Django的syncdb在MySQL中失败,错误码:150

12 投票
4 回答
6592 浏览
提问于 2025-04-17 01:55

首先,这是我现在的设置:

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 引擎对 Django 生成的 SQL 有些不满意。

目前,我找到的唯一解决办法是自己创建表,然后使用 inspectDB 来生成模型……

有没有什么解决方案呢?谢谢!

4 个回答

4

MySQL的文档上说:

无法创建表。如果错误信息提到错误150,说明创建表失败是因为外键约束没有正确设置。如果错误信息提到错误-1,可能是因为表中有一个列名和InnoDB内部表的名字重复了。

把你的模型代码贴在这里,让我们看看哪里可能出问题。如果你不能贴,或者不知道哪里出错,可以尝试逐步检查代码的不同版本:把一半的应用程序关闭,看看是否能正常同步,然后再检查包含有问题模型的那部分,依此类推。

15

在使用Django 1.5的时候,遇到一个问题,就是MySQL默认用Innodb引擎来创建表。解决这个问题的方法是把以下内容添加到数据库的设置中,但这样做又引发了约束方面的问题:

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

}
0

我找到了问题的根源。当创建两个有外键关系的InnoDB表时,外键列必须明确地建立索引,这在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问题单

撰写回答