Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

changing isolation level #120

Closed
ssfking opened this issue Mar 20, 2013 · 5 comments
Closed

changing isolation level #120

ssfking opened this issue Mar 20, 2013 · 5 comments
Labels

Comments

@ssfking
Copy link

ssfking commented Mar 20, 2013

How do you change the isolation level of a session/transaction without going down to the sqlalchemy layer?

@fjbsantiago
Copy link

fjbsantiago commented Oct 4, 2016

I don't think it is possible yet. This was the simplest way I found to do it.

from sqlalchemy import create_engine, event

engine = create_engine("sqlite:///myfile.db")

@event.listens_for(engine, "connect")
def do_connect(dbapi_connection, connection_record):
    # disable pysqlite's emitting of the BEGIN statement entirely.
    # also stops it from emitting COMMIT before any DDL.
    dbapi_connection.isolation_level = None

From: http://docs.sqlalchemy.org/en/rel_1_0/dialects/sqlite.html#serializable-isolation-savepoints-transactional-ddl

@cript0nauta
Copy link

Hi! I wrote a custom SQLAlchemy class to do this, since create_engine is called inside Flask-SQLAlchemy code. Maybe someone could find this useful:

from flask_sqlalchemy import (
    SQLAlchemy as OriginalSQLAlchemy,
    _EngineConnector
)

class SQLAlchemy(OriginalSQLAlchemy):
    """Override to fix issues when doing a rollback with sqlite driver
    See http://docs.sqlalchemy.org/en/rel_1_0/dialects/sqlite.html#serializable-isolation-savepoints-transactional-ddl
    and https://bitbucket.org/zzzeek/sqlalchemy/issues/3561/sqlite-nested-transactions-fail-with
    for furhter information"""

    # TODO: only do this on sqlite, not on postgres nor other RDBMS!

    def make_connector(self, app=None, bind=None):
        """Creates the connector for a given state and bind."""
        return CustomEngineConnector(self, self.get_app(app), bind)


class CustomEngineConnector(_EngineConnector):
    """Used by overrideb SQLAlchemy class to fix rollback issues"""

    def get_engine(self):
        # Use an existent engine and don't register events if possible
        uri = self.get_uri()
        echo = self._app.config['SQLALCHEMY_ECHO']
        if (uri, echo) == self._connected_for:
            return self._engine

        # Call original metohd and register events
        rv = super(CustomEngineConnector, self).get_engine()
        with self._lock:
            @event.listens_for(rv, "connect")
            def do_connect(dbapi_connection, connection_record):
                # disable pysqlite's emitting of the BEGIN statement entirely.
                # also stops it from emitting COMMIT before any DDL.
                dbapi_connection.isolation_level = None

            @event.listens_for(rv, "begin")
            def do_begin(conn):
                # emit our own BEGIN
                conn.execute("BEGIN")
        return rv


db = SQLAlchemy()

@DenisKuplyakov
Copy link

Are there any progress on this? We were surprissed by postgres default of "READ COMMITED" instead of "READ REPEATED" today, but it looks there is no way to pass parameter.

@brodul
Copy link

brodul commented Sep 11, 2018

There is a PR open that will allow passing engine options to the constructor. #487

For now there is a simple clean workaround:

from flask_sqlalchemy import SQLAlchemy


class SQLiteAlchemy(SQLAlchemy):
    def apply_driver_hacks(self, app, info, options):
        options.update({
            'isolation_level': 'READ COMMITTED',
        })
        super(SQLiteAlchemy, self).apply_driver_hacks(app, info, options)


db = SQLiteAlchemy(app)

@davidism davidism added the config label Feb 2, 2019
@rsyring
Copy link
Contributor

rsyring commented Mar 8, 2019

The ability to customize the session will be taken care of by #166.

@rsyring rsyring closed this as completed Mar 8, 2019
@pallets-eco pallets-eco deleted a comment from est May 21, 2020
@pallets-eco pallets-eco locked and limited conversation to collaborators May 21, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Development

No branches or pull requests

7 participants