指定多个数据库时,Django syncdb 尝试插入重复行

Posted

技术标签:

【中文标题】指定多个数据库时,Django syncdb 尝试插入重复行【英文标题】:Django syncdb trying to insert duplicate rows when multiple databases are specified 【发布时间】:2012-05-16 20:47:20 【问题描述】:

我正在为多个数据库配置我的 Django 应用程序,作为权宜之计,我在我的 settings.py 中使用以下配置:

READ_DATABASE = 
    'ENGINE': 'django.db.backends.mysql',
    'NAME': 'thedatabase',
    'USER': 'read_only',
    'PASSWORD': '',
    'OPTIONS': 
        'init_command': 'SET storage_engine=INNODB'
    


WRITE_DATABASE = 
    'ENGINE': 'django.db.backends.mysql',
    'NAME': 'thedatabase',
    'USER': 'root',
    'PASSWORD': '',
    'OPTIONS': 
        'init_command': 'SET storage_engine=INNODB'
    


DATABASES = 'default': WRITE_DATABASE,
             'read': READ_DATABASE

它们指向同一个数据库,以模拟主从对。 read_only 用户,您可能猜到了,只有读取权限。

我的数据库路由器如下所示:

from django.conf import settings 

class MasterSlaveRouter(object):

    def db_for_read(self, model, **hints):
        return 'read' 

    def db_for_write(self, model, **hints):
        return 'default' 

    def allow_relation(self, db1, db2, **hints):
        return True

    def allow_syncdb(self, db, model):
        return db in ('default',)

运行syncdb时,现在设置超级用户后立即崩溃,并出现错误:

django.db.utils.IntegrityError: (1062, "Duplicate entry 'auth-permission' for key 'app_label'")

未能执行的违规 SQL 是:

INSERT INTO `django_content_type` (`name`, `app_label`, `model`) VALUES (permission, auth, permission)

此错误在我的settings.py 中指定第二个读取数据库时发生,当仅存在default 数据库时,syncdb 命令成功完成。

有什么建议可能导致这种情况吗?

编辑: Django 版本是 1.2.3

【问题讨论】:

如何指定DATABASE_ROUTERSpost_syncdb 好像被触发了两次。 DATABASE_ROUTERS = ['path.to.MasterSlaveRouter'] 在我的配置文件中。 好的,你能显示实际的path.to吗;并尝试将MasterSlaveRouter放入设置中,然后设置DATABASE_ROUTERS = ['settings.MasterSlaveRouter'] 路由器肯定被击中 - 我已将 import pdb; pdb.set_trace 添加到 db_for_read/write 方法中验证这一点。断点被击中,路由器的可发现性绝对不是问题。不过感谢您的建议。 是的,我并不是说它没有被使用过。我的意思是导入可能会导致post_syncdb 被绑定多次,因此 contenttypes 想要为 Permission 模型生成 content_type 两次,因此出现错误 【参考方案1】:

经过几个小时的修改,我推断发生这种情况的原因是因为某些 Django 模型(在本例中为 django.contrib.contenttype.models.ContentType,但也有 django.contrib.site.models.Site)有自己的 inbuilt caching mechanism。

由于我已经为同一个数据库设置了两个不同的连接,这导致了一个问题,因为在写入连接上写入 ContentType 模型并没有使只读连接的 contenttype 缓存失效.

解决方案是将我的 db_for_read 方法更改为如下所示:

def db_for_read(self, model, **hints): if model._meta.app_label in ('contenttypes', 'sites'): 返回'写' 别的: 返回“阅读”

【讨论】:

以上是关于指定多个数据库时,Django syncdb 尝试插入重复行的主要内容,如果未能解决你的问题,请参考以下文章

运行 Django 的 syncdb 时 OSX 10.7.3 上的 Postgresql 套接字错误

运行 Django 的 ./manage.py syncdb 时自动创建管理员用户

在 django 中,如何从初始化脚本中调用子命令“syncdb”?

使用mysql的django上的syncdb错误

Django:Syncdb 错误地警告多对多字段已过时

django 在服务器上的 syncdb 期间出错