Django的syncdb在MySQL中失败,错误码:150
首先,这是我现在的设置:
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 个回答
MySQL的文档上说:
无法创建表。如果错误信息提到错误150,说明创建表失败是因为外键约束没有正确设置。如果错误信息提到错误-1,可能是因为表中有一个列名和InnoDB内部表的名字重复了。
把你的模型代码贴在这里,让我们看看哪里可能出问题。如果你不能贴,或者不知道哪里出错,可以尝试逐步检查代码的不同版本:把一半的应用程序关闭,看看是否能正常同步,然后再检查包含有问题模型的那部分,依此类推。
在使用Django 1.5的时候,遇到一个问题,就是MySQL默认用Innodb引擎来创建表。解决这个问题的方法是把以下内容添加到数据库的设置中,但这样做又引发了约束方面的问题:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'etc....',
'OPTIONS': {
"init_command": "SET storage_engine=MyISAM",
},
},
}
我找到了问题的根源。当创建两个有外键关系的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问题单。