Django

Code

Ticket #3460: 3640_r9734-autocommit.diff

File 3640_r9734-autocommit.diff, 6.7 kB (added by Richard Davies <richard.davies@elastichosts.com>, 1 year ago)

Configurable native autocommit

  • django/db/backends/__init__.py

    old new  
    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

    old new  
    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

    old new  
    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

    old new  
    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