#32965 closed Bug (invalid)
Django related manager allways choose db_for_read router and fail update/delete
Reported by: | Regressor | Owned by: | nobody |
---|---|---|---|
Component: | Database layer (models, ORM) | Version: | 3.1 |
Severity: | Normal | Keywords: | related manager, db_for_read, exception, db, router |
Cc: | Triage Stage: | Unreviewed | |
Has patch: | no | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | no |
Easy pickings: | no | UI/UX: | no |
Description
We have a large project running django 3.1.12. It is use aws aurora rds cluster for database and we tried to take most of it. Wee need to use read replicas to be able fast db overload response. So we made routers, started multiple db config, fixed number read replica lag issues and finally got error "cannot execute DELETE in a read-only transaction" in simple field .delete()
So. Example: We have a model with a generic relation:
mentor_binds = GenericRelation('MentorBind', object_id_field='parent_object_id', content_type_field='parent_content_type')
And an exception when trying to clean binds:
instance.mentor_binds.all().delete()
The only workaround is to add .using('default') before .delete() / .update()
I beelive this is a bug in GenericRelatedManager's _apply_rel_filters() method. There is a string in it:
db = self._db or router.db_for_read(self.model, instance=self.instance)
But I can't say this is the only place with such problem, so I had to add .using('default') before all .update() and .delete() - ~400 changes
Change History (2)
follow-up: 2 comment:1 by , 3 years ago
Resolution: | → invalid |
---|---|
Status: | new → closed |
comment:2 by , 3 years ago
Replying to Mariusz Felisiak:
Thanks for this report, however IMO it's not a bug. It's documented that
DELETE
will be executed on the same database that was used to retrieve the object, so you need to useusing
. I would recommend to use related manager's methods i.e.clear()
instead of chainingall()
anddelete()
, e.g.instance.mentor_binds.clear()
, andset()
instead ofupdate()
, e.g.instance.mentor_binds.set(...)
.
Oh. It try to delete/update on read database, but this is not a bug because it documented. Ok. This automatic database routers has too many issues to be used in real life. There was ~8000 lines changed in our project to start working with read replicas and it still doesn't work as expected. It looks like we should just disable this config and try aws serverless rds.
Thanks for this report, however IMO it's not a bug. It's documented that
DELETE
will be executed on the same database that was used to retrieve the object, so you need to useusing
. I would recommend to use related manager's methods i.e.clear()
instead of chainingall()
anddelete()
, e.g.instance.mentor_binds.clear()
, andset()
instead ofupdate()
, e.g.instance.mentor_binds.set(...)
.