Jas*_*enX 7 django django-models
我有一个正在生产中运行的 Django 应用程序。它的数据库有主要的写入实例和一些读取副本。我通常DATABASE_ROUTERS根据是否需要读取或写入在写入实例和读取副本之间进行路由。
我遇到了一种情况,由于用户请求,我必须对对象进行一些异步处理。动作顺序是:
现在,celery 作业可能会在 10 毫秒或 10 分钟内启动,具体取决于队列。当它最终启动时,celery 作业首先尝试根据提供的 ID 加载对象。最初,我在执行 a 时遇到了问题my_obj = MyModel.objects.get(pk=given_id),因为此时将使用只读副本,如果队列为空并且 celery 作业在触发后立即运行,则对象可能尚未传播到只读副本。
我通过替换为解决了这个问题my_obj = MyModel.objects.get(pk=given_id)--my_obj = MyModel.objects.using('default').get(pk=given_id)这确保了从我的 write-db-instance 读取对象并且该对象始终可用。
然而,现在我遇到了另一个我没有预料到的问题。
my_obj.certain_many_to_many_objects.all()由于 ORM 是惰性的,调用会触发对数据库的另一个调用。该调用是在只读副本上完成的。我希望它会坚持我定义的数据库,using但事实并非如此。有没有办法强制所有子元素对象使用相同的 write-db-instance?
我怀疑您的自定义数据库路由器需要调整。默认行为没有应该提供您所需的数据库粘性
\n\n\n\n默认路由方案确保对象保持\n\xe2\x80\x98粘性\xe2\x80\x99 到其原始数据库(即,从 foo 数据库检索的对象将保存在同一数据库上)。\n[。 ..]\n\xe2\x80\x99 不需要执行任何操作来激活默认路由方案 \xe2\x80\x93\nit 在每个 Django 上都提供了 \xe2\x80\x98 开箱即用 \xe2\x80\x99项目。
\n
因此,您的数据库路由器只需要预先提供此行为,这在 99.9% 的情况下可能是正确的做法。
\ndef db_for_read(model, **hints):\n instance = hints.get(\'instance\')\n if instance is not None and instance._state.db:\n return instance._state.db\n # else return your read replica\n return \'read-only\' # or whatever it\'s called\nRun Code Online (Sandbox Code Playgroud)\n\n
| 归档时间: |
|
| 查看次数: |
1466 次 |
| 最近记录: |