]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
add BEGIN workaround to pysqlite docs, [ticket:2219]
authorMike Bayer <mike_mp@zzzcomputing.com>
Tue, 6 Dec 2011 17:41:01 +0000 (12:41 -0500)
committerMike Bayer <mike_mp@zzzcomputing.com>
Tue, 6 Dec 2011 17:41:01 +0000 (12:41 -0500)
lib/sqlalchemy/dialects/sqlite/base.py
lib/sqlalchemy/dialects/sqlite/pysqlite.py

index f0c9a0ccaa52d990fa8f3cdb05069d74ff168890..9d5e070b3dcfa665ecc4cd8c4356c572d87b05eb 100644 (file)
@@ -46,10 +46,12 @@ to the Table construct::
 Transaction Isolation Level
 ---------------------------
 
-:func:`create_engine` accepts an ``isolation_level`` parameter which results in 
+:func:`.create_engine` accepts an ``isolation_level`` parameter which results in 
 the command ``PRAGMA read_uncommitted <level>`` being invoked for every new 
 connection.   Valid values for this parameter are ``SERIALIZABLE`` and 
 ``READ UNCOMMITTED`` corresponding to a value of 0 and 1, respectively.
+See the section :ref:`pysqlite_serializable` for an important workaround
+when using serializable isolation with Pysqlite.
 
 """
 
index ad8d5c6f9f1343d3747f82eb39b427fa1c2cd2fb..63832b8f37059154be00270c67f015327027ce87 100644 (file)
@@ -182,6 +182,31 @@ require unicode, however, so that non-``unicode`` values passed inadvertently
 will emit a warning.  Pysqlite will emit an error if a non-``unicode`` string
 is passed containing non-ASCII characters.
 
+.. _pysqlite_serializable:
+
+Serializable Transaction Isolation
+----------------------------------
+
+The pysqlite DBAPI driver has a long-standing bug in which transactional
+state is not begun until the first DML statement, that is INSERT, UPDATE
+or DELETE, is emitted.  A SELECT statement will not cause transactional
+state to begin.   While this mode of usage is fine for typical situations
+and has the advantage that the SQLite database file is not prematurely 
+locked, it breaks serializable transaction isolation, which requires
+that the database file be locked upon any SQL being emitted.
+
+To work around this issue, the ``BEGIN`` keyword can be emitted
+at the start of each transaction.   The following recipe establishes
+a :meth:`.ConnectionEvents.begin` handler to achieve this::
+
+    from sqlalchemy import create_engine, event
+
+    engine = create_engine("sqlite:///myfile.db", isolation_level='SERIALIZABLE')
+
+    @event.listens_for(engine, "begin")
+    def do_begin(conn):
+        conn.execute("BEGIN")
+
 """
 
 from sqlalchemy.dialects.sqlite.base import SQLiteDialect, DATETIME, DATE