Django多个数据库和“无法在只读事务中执行”错误

时间:2014-03-06 19:39:30

标签: database django

我使用Django docs在主从配置中设置多个数据库。我的路由器设置正确,我可以看到读取和写入到正确的相应数据库,但我的一些API调用遇到错误:

cannot execute [UPDATE or DELETE] in a read-only transaction

在发生这种情况的API处理程序中,我正在更新或删除一些其他模型作为同一调用的一部分,并且Django似乎想要为这些事务使用从数据库而不是master。

A workaround I found是在.using('default')update()之前链接delete(),这基本上迫使Django使用master数据库进行更新或删除。但是这感觉很笨拙,而且我想要确保没有更好的方法来做到这一点。

非常感谢任何帮助。

3 个答案:

答案 0 :(得分:1)

您是否尝试过以下操作?这是从Django文档页面中复制出来的:

import random

class MasterSlaveRouter(object):
    def db_for_read(self, model, **hints):
        """
        Reads go to a randomly-chosen slave.
        """
        return random.choice(['slave1', 'slave2'])

    def db_for_write(self, model, **hints):
        """
        Writes always go to master.
        """
        return 'master'

    def allow_relation(self, obj1, obj2, **hints):
        """
        Relations between objects are allowed if both objects are
        in the master/slave pool.
        """
        db_list = ('master', 'slave1', 'slave2')
        if obj1._state.db in db_list and obj2._state.db in db_list:
            return True
        return None

    def allow_migrate(self, db, model):
        """
        All non-auth models end up in this pool.
        """
        return True

最后,在设置文件中,我们添加以下内容(用实际的python路径替换path.to.到定义路由器的模块):

DATABASE_ROUTERS = ['path.to.AuthRouter', 'path.to.MasterSlaveRouter']

答案 1 :(得分:0)

也得到了这个,并为 django 开发人员张贴了一张票。 这是:https://code.djangoproject.com/ticket/32965

有一个答案。有 Django 文档说 .delete() 和 .update() 使用用于检索对象的相同数据库(始终为只读!)。所以这不是错误,而是未来,因为他们说它记录在案。

所以有两种方法可以解决这个问题:

  1. 在每个 .delete() 和 .update() 之前添加 using('xxxx')
  2. 将 .delete() 替换为 .clear() 并将 .update() 替换为 .set()

答案 2 :(得分:-1)

如果没有在代码中散布.using('default'),似乎无法做到这一点。