Search code examples
pythondjangocursormultiprocessingdjango-database

Is connection.cursor() thread-safe in Django 1.6?


AFAIK In Django 1.6 the cursor is shared between requests and open a new connection when needed. However I couldn't find any information about how connection.cursor() method works and how can I should use connection.cursor() method in different processes in documentation.

Most code I have seen doesn't close cursor object returned from connection.cursor() so I assume that Django automatically close the cursor object returned from connection.cursor() when the request is finished, but what if I call connection.cursor() in a different process? Should I close that cursor when terminating the process or the wrapper function of cursor automatically kills itself?


Solution

  • Thread safety depends on db connection implementation, see Python Database API Specification v2.0 for possible cases:

    threadsafety: Integer constant stating the level of thread safety the interface supports. Possible values are:

    threadsafety  Meaning
    0             Threads may not share the module.
    1             Threads may share the module, but not connections.
    2             Threads may share the module and connections.
    3             Threads may share the module, connections and cursors.
    

    for example, MySQL, PostgreSQL and Oracle:

    >>> import MySQLdb
    >>> MySQLdb.threadsafety
    1
    >>> import psycopg2
    >>> psycopg2.threadsafety
    2
    >>> import cx_Oracle
    >>> cx_Oracle.threadsafety
    2
    

    So it seems that no django supported DB connection is thread safe on cursor level.

    Normally, cursors are closed with __del__ method, i.e. when garbage collected, or when thread is normally terminated (as contrary to when it's killed, as daemon threads may end up). I recall some bugs in cursors handling on specific platforms, namely some issues with oracle's famous ORA-01000 Too many cursors error. Quick google search revealed a bug for Jython, but I am quite sure I had issues in CPython as well. See also this ticket