Opened 8 years ago

Closed 8 years ago

#26935 closed Bug (duplicate)

DB connections stuck in closed state when using Django ORM in daemon

Reported by: Mike Charnoky Owned by: nobody
Component: Database layer (models, ORM) Version: 1.9
Severity: Normal Keywords:
Cc: Triage Stage: Unreviewed
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

Situation:

  1. A long-running daemon process is using the Django ORM
  2. The underlying database gets restarted, causing existing db connection(s) to become invalid

Problem:
A subsequent db read using the ORM fail with the exception:

  File "main.py", line 22, in <module>
    testread()
  File "main.py", line 14, in testread
    user = User.objects.all()[0]
  File "/home/noky/Downloads/django-standalone/venv/local/lib/python2.7/site-packages/django/db/models/query.py", line 297, in __getitem__
    return list(qs)[0]
  File "/home/noky/Downloads/django-standalone/venv/local/lib/python2.7/site-packages/django/db/models/query.py", line 258, in __iter__
    self._fetch_all()
  File "/home/noky/Downloads/django-standalone/venv/local/lib/python2.7/site-packages/django/db/models/query.py", line 1074, in _fetch_all
    self._result_cache = list(self.iterator())
  File "/home/noky/Downloads/django-standalone/venv/local/lib/python2.7/site-packages/django/db/models/query.py", line 52, in __iter__
    results = compiler.execute_sql()
  File "/home/noky/Downloads/django-standalone/venv/local/lib/python2.7/site-packages/django/db/models/sql/compiler.py", line 848, in execute_sql
    cursor.execute(sql, params)
  File "/home/noky/Downloads/django-standalone/venv/local/lib/python2.7/site-packages/django/db/backends/utils.py", line 64, in execute
    return self.cursor.execute(sql, params)
  File "/home/noky/Downloads/django-standalone/venv/local/lib/python2.7/site-packages/django/db/utils.py", line 95, in __exit__
    six.reraise(dj_exc_type, dj_exc_value, traceback)
  File "/home/noky/Downloads/django-standalone/venv/local/lib/python2.7/site-packages/django/db/backends/utils.py", line 64, in execute
    return self.cursor.execute(sql, params)
OperationalError: terminating connection due to administrator command
server closed the connection unexpectedly
	This probably means the server terminated abnormally
	before or while processing the request.

Further subsequent db reads using the ORM yield a different (yet consistent) exception:

  File "main.py", line 22, in <module>
    testread()
  File "main.py", line 14, in testread
    user = User.objects.all()[0]
  File "/home/noky/Downloads/django-standalone/venv/local/lib/python2.7/site-packages/django/db/models/query.py", line 297, in __getitem__
    return list(qs)[0]
  File "/home/noky/Downloads/django-standalone/venv/local/lib/python2.7/site-packages/django/db/models/query.py", line 258, in __iter__
    self._fetch_all()
  File "/home/noky/Downloads/django-standalone/venv/local/lib/python2.7/site-packages/django/db/models/query.py", line 1074, in _fetch_all
    self._result_cache = list(self.iterator())
  File "/home/noky/Downloads/django-standalone/venv/local/lib/python2.7/site-packages/django/db/models/query.py", line 52, in __iter__
    results = compiler.execute_sql()
  File "/home/noky/Downloads/django-standalone/venv/local/lib/python2.7/site-packages/django/db/models/sql/compiler.py", line 846, in execute_sql
    cursor = self.connection.cursor()
  File "/home/noky/Downloads/django-standalone/venv/local/lib/python2.7/site-packages/django/db/backends/base/base.py", line 233, in cursor
    cursor = self.make_cursor(self._cursor())
  File "/home/noky/Downloads/django-standalone/venv/local/lib/python2.7/site-packages/django/db/backends/base/base.py", line 206, in _cursor
    return self.create_cursor()
  File "/home/noky/Downloads/django-standalone/venv/local/lib/python2.7/site-packages/django/db/utils.py", line 95, in __exit__
    six.reraise(dj_exc_type, dj_exc_value, traceback)
  File "/home/noky/Downloads/django-standalone/venv/local/lib/python2.7/site-packages/django/db/backends/base/base.py", line 206, in _cursor
    return self.create_cursor()
  File "/home/noky/Downloads/django-standalone/venv/local/lib/python2.7/site-packages/django/db/backends/postgresql/base.py", line 210, in create_cursor
    cursor = self.connection.cursor()
InterfaceError: connection already closed

Environment:

  • Ubuntu 14.04
  • PostgreSQL 9.5
  • Django 1.9.8
  • psycopg2 2.6.2

To reproduce problem:

  • Download attached project files and untar
  • Create a PostgreSQL database testdb
  • Edit settings.py to setup db settings
  • Run setup.sh to create virtualenv, install Django and run the "daemon"
  • The daemon simply writes a record to the db, then constantly queries the db using the Django ORM. Every 5 seconds, a db query is made and the result is printed
  • Stop PostgreSQL and restart it: sudo service postgresql restart
  • The daemon application will fail to reconnect to the database and the above exceptions will be output
  • It is interesting to note that if you modify the daemon process to write to the db in it's main loop, the problem does not manifest (uncomment the testwrite() line in main.py to see this behavior).

Workaround:
I have come up with the following patch to workaround the problem, though it is PostgreSQL specific (it makes use of the connection.closed attribute unique to psycopg). Not sure of a general fix for this problem.

--- django/db/backends/base/base.py.orig	2016-07-22 15:30:36.655291625 -0400
+++ django/db/backends/base/base.py	2016-07-22 15:37:03.419337590 -0400
@@ -197,6 +197,9 @@
         if self.connection is None:
             with self.wrap_database_errors:
                 self.connect()
+        elif self.connection.closed:
+            with self.wrap_database_errors:
+                self.connect()

Attachments (1)

django-daemon-test.tgz (1.1 KB ) - added by Mike Charnoky 8 years ago.
barebones django "daemon" project that reproduces problem

Download all attachments as: .zip

Change History (4)

by Mike Charnoky, 8 years ago

Attachment: django-daemon-test.tgz added

barebones django "daemon" project that reproduces problem

comment:1 by Tim Graham, 8 years ago

I think this is a duplicate of #24810. Can you confirm?

comment:2 by Aymeric Augustin, 8 years ago

As usual when this topic comes up, the patch throws transactional integrity to the wind, which isn't acceptable.

comment:3 by Tim Graham, 8 years ago

Resolution: duplicate
Status: newclosed
Note: See TracTickets for help on using tickets.
Back to Top