#36964: Clarify how persistent connections interact with runserver
-------------------------------------+-------------------------------------
Reporter: Adam Sołtysik | Owner: Youssef
Type: | Tarek Ali
Cleanup/optimization | Status: assigned
Component: Documentation | Version: 5.2
Severity: Normal | Resolution:
Keywords: | Triage Stage: Accepted
Has patch: 1 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Comment (by blighj):
Thanks for the feedback, I take your point. To be honest I've used it
myself in my last gig, for the same reasons, we had a shared db server
over the cloud used by our cms team (5 or 6 people max) and every so often
we'd all get a "sorry, too many clients already" error and all work was
halted until someone kicked the db server. The first few times it happened
it was painful as it took us a while to realise the db needed restarting.
We never figured out what was the cause and it was a rare occurrence,
dozen times a year, though often in clusters. We could see that the db
server was full of idle connections but couldn't figure out where they
were coming from. I now highly suspect it was the persistent connections.
But yeah we had it on more because we had it on in production and thought
it would help speed up dev without ever knowing about the docs
recommendation for runserver.
The question to decide is whether Django's reference documentation on
databases should give a soft recommendation to use something that was not
designed to work, may or may not work, and may cause a hard-to-diagnose
failure.
A community blog post, with lots of benchmarks and going into details on
the inner workings and tradeoffs, I can see that no problem. Something in
the Django docs, not so sure...
What if we said.
{{{#!diff
--- a/docs/ref/databases.txt
+++ b/docs/ref/databases.txt
@@ -89,9 +89,11 @@
to be reused. This will help keep the number of simultaneous connections
to
this database small.
-The development server creates a new thread for each request it handles,
-negating the effect of persistent connections. Don't enable them during
-development.
+The development server isn't designed for persistent connections. It
creates
+a new thread for each HTTP connection it handles, so database connections
+aren't reused between them and can be left orphaned. You may see one
reused
+while a client keeps an HTTP connection alive, but that's outside your
+control. Persistent connections shouldn't be enabled during development.
When Django establishes a connection to the database, it sets up
appropriate
parameters, depending on the backend being used. If you enable persistent
}}}
These seem like accurate claims for the docs to me. It acknowledges how
persistent connections may appear to work, points out that it isn't
designed, and gives a clue to the failure mode that would have helped my
old team. It also downgrades the `don't` to a `shouldn't`, if people want
to take the risk, that's on them. And it doesn't open up Django
maintainers to bug reports asking why it doesn't work reliably, or where
all these idle connections have come from.
To double check the claims were accurate I ran a little test against
Postgres, with 40 requests with and without keep alive:
||= =||= idle backends =||
|| baseline || 0 ||
|| 40 requests, 1 keep-alive connection || 1 ||
|| 40 requests, 40 separate connections || 41 ||
|| after `gc.collect()` || 0 ||
So you can see from the first pass there is a single connection serving
all 40 requests. The second creates one per client connection and leaves
them sitting idle in the database until they're garbage collected, (41
because the keep-alive connection from the first pass is still there too).
--
Ticket URL: <
https://code.djangoproject.com/ticket/36964#comment:20>