Ticket #3460: 3640_r9734-autocommit.diff

File 3640_r9734-autocommit.diff, 6.7 KB (added by Richard Davies <richard.davies@…>, 7 years ago)

Configurable native autocommit

  • django/db/backends/__init__.py

     
    3131        if self.connection is not None:
    3232            return self.connection.rollback()
    3333
     34    def _enter_transaction_management(self, managed):
     35        pass
     36
     37    def _leave_transaction_management(self, managed):
     38        pass
     39
    3440    def _savepoint(self, sid):
    3541        if not self.features.uses_savepoints:
    3642            return
     
    7480    # If True, don't use integer foreign keys referring to, e.g., positive
    7581    # integer primary keys.
    7682    related_fields_match_type = False
     83    native_autocommit = False
    7784
    7885class BaseDatabaseOperations(object):
    7986    """
  • django/db/backends/postgresql_psycopg2/base.py

     
    44Requires psycopg 2: http://initd.org/projects/psycopg2
    55"""
    66
     7from django.conf import settings
    78from django.db.backends import *
    89from django.db.backends.postgresql.operations import DatabaseOperations as PostgresqlDatabaseOperations
    910from django.db.backends.postgresql.client import DatabaseClient
     
    2829
    2930class DatabaseFeatures(BaseDatabaseFeatures):
    3031    needs_datetime_string_cast = False
    31     uses_savepoints = True
    3232
    3333class DatabaseOperations(PostgresqlDatabaseOperations):
    3434    def last_executed_query(self, cursor, sql, params):
     
    5959        super(DatabaseWrapper, self).__init__(*args, **kwargs)
    6060       
    6161        self.features = DatabaseFeatures()
     62        if settings.DATABASE_OPTIONS.get('native_autocommit', False):
     63          self.features.native_autocommit = True
     64          self.features.uses_savepoints = False
     65          self._isolation_level = 0
     66        else:
     67          self.features.native_autocommit = False
     68          self.features.uses_savepoints = True
     69          self._isolation_level = 1
    6270        self.ops = DatabaseOperations()
    6371        self.client = DatabaseClient()
    6472        self.creation = DatabaseCreation(self)
    6573        self.introspection = DatabaseIntrospection(self)
    6674        self.validation = BaseDatabaseValidation()
     75 
     76    def _enter_transaction_management(self, managed):
     77        """Manages the mapping of transaction management to isolation levels"""
    6778
     79        if self.features.native_autocommit and managed and self._isolation_level == 0:
     80            try:
     81                if self.connection != None:
     82                    self.connection.set_isolation_level(1)
     83            finally:
     84                self._isolation_level = 1
     85                self.features.uses_savepoints = True
     86
     87    def _leave_transaction_management(self, managed):
     88        """Manages the mapping of transaction management to isolation levels"""
     89
     90        if self.features.native_autocommit and not managed and self._isolation_level == 1:
     91            try:
     92                if self.connection != None:
     93                    self.connection.set_isolation_level(0)
     94            finally:
     95                self._isolation_level = 0
     96                self.features.uses_savepoints = False
     97
    6898    def _cursor(self, settings):
    6999        set_tz = False
    70100        if self.connection is None:
     
    81111                conn_string += " host=%s" % settings.DATABASE_HOST
    82112            if settings.DATABASE_PORT:
    83113                conn_string += " port=%s" % settings.DATABASE_PORT
    84             self.connection = Database.connect(conn_string, **self.options)
    85             self.connection.set_isolation_level(1) # make transactions transparent to all cursors
     114            x = self.options.copy()
     115            x.pop('native_autocommit', '')
     116            self.connection = Database.connect(conn_string, **x)
     117            self.connection.set_isolation_level(self._isolation_level)
    86118            self.connection.set_client_encoding('UTF8')
    87119        cursor = self.connection.cursor()
    88120        cursor.tzinfo_factory = None
  • django/db/transaction.py

     
    4040# database commit.
    4141dirty = {}
    4242
    43 def enter_transaction_management():
     43def enter_transaction_management(managed=True):
    4444    """
    4545    Enters transaction management for a running thread. It must be balanced with
    4646    the appropriate leave_transaction_management call, since the actual state is
     
    5858        state[thread_ident].append(settings.TRANSACTIONS_MANAGED)
    5959    if thread_ident not in dirty:
    6060        dirty[thread_ident] = False
     61    connection._enter_transaction_management(managed)
    6162
    6263def leave_transaction_management():
    6364    """
     
    6566    over to the surrounding block, as a commit will commit all changes, even
    6667    those from outside. (Commits are on connection level.)
    6768    """
     69    connection._leave_transaction_management(is_managed())
    6870    thread_ident = thread.get_ident()
    6971    if thread_ident in state and state[thread_ident]:
    7072        del state[thread_ident][-1]
     
    216218    """
    217219    def _autocommit(*args, **kw):
    218220        try:
    219             enter_transaction_management()
     221            enter_transaction_management(managed=False)
    220222            managed(False)
    221223            return func(*args, **kw)
    222224        finally:
  • docs/ref/databases.txt

     
    260260column types have a maximum length restriction of 255 characters, regardless
    261261of whether ``unique=True`` is specified or not.
    262262
     263.. _postgresql-notes:
     264
     265PostgreSQL notes
     266================
     267
     268Django supports PostgreSQL using the psycopg_ package. Django supports both
     269version 1 and 2. (When you configure Django's database layer, specify either
     270``postgresql`` [for version 1] or ``postgresql_psycopg2`` [for version 2].)
     271
     272Native Autocommit
     273-----------------
     274
     275By default, Django database backends run with a permanently open
     276transaction, as per the Python DB-API. Django simulates autocommit behaviour
     277by committing this transaction automatically (e.g. in ``save()``). For
     278PostgreSQL, this corresponds to running in ``set_isolation_level(1)``.
     279
     280For higher performance, ``postgresql_psycopg2`` can be configured to run
     281without an open connection when Django is in autocommit mode. This
     282corresponds to PostgreSQL ``set_isolation_level(0)`` and is configured
     283with::
     284
     285    DATABASE_OPTIONS = {'native_autocommit':True}
     286
     287.. _psycopg: http://initd.org/pub/software/psycopg/
     288
    263289.. _sqlite-notes:
    264290
    265291SQLite notes
Back to Top