[Twisted-Python] How to correctly run Sqlite with Twisted?
ex vito
ex.vitorino at gmail.com
Wed Sep 20 02:24:43 MDT 2017
On 2017-09-19, at 21:59, Goffi <goffi at goffi.org> wrote:
> I'm using Sqlite3 module through Twisted's enterpirse.adbapi, I create the
> ConnectionPool instance like this:
>
> self.dbpool = ConnectionPool("sqlite3", db_filename,
> check_same_thread=False)
>
> You can see the code at https://repos.goffi.org/sat/file/tip/src/memory/sqlite.py
>
> Sometime, the writing is failing with following exception:
>
> Failure instance: Traceback: <class 'sqlite3.OperationalError'>: database is
> locked
>
> So I wonder if the database is correctly used, did anybody experienced
> something similar with Twisted and Sqlite ?
>
> Should I just augment timeout as advised at https://stackoverflow.com/a/
> 8618328? Looks like more a workaround than a clean solution.
>
> Python 2 documentation doesn't talk about check_same_thread argument, but
> Python 3 at https://docs.python.org/3.5/library/sqlite3.html#sqlite3.connect
> says that writing operation should be serialized by the user (I thought it was
> the default as said in https://sqlite.org/threadsafe.html), how should I
> achieve that?
>
> Also PRAGMA are not working (specially "PRAGMA foreign_keys = ON"), I guess
> because of multi-threading, what is the good way to activate foreign_keys for
> all following request?
I would subscribe to Moshe's and Jean-Paul's suggestions of using higher-level tools to handle database interactions. If, however, you'd rather continue with the adbapi approach, here are a few tips that may help your diagnostic, given that behavior you are observing seems to result from multi-threaded/multi-process interactions:
- Confirm you have no other SQLite client at play, locking your data somehow.
- Correct serialization of independent SQL queries/transactions may be a complex topic.
- But you can try forcing the ConnectionPool thread count to 1 via the cp_min/cp_max init args.
- For your PRAGMA statements you should probably use the cp_openfun ConnectionPool init arg.
- Using the undocumented "check_same_thread" on Python 2 seems pointless.
(not sure it is, though; I did not look at the underlying Python 2 stdlib code)
Lastly:
I have experienced issues with SQLite3 + Python on one occasion in the past: depending on the platform, SQLite itself is/is-not distributed with Python, IIRC; for diagnostics, confirm the exact version of the sqlite .SO / .DLL in use and, ideally, its compile time options. I recall my troubles were between CentOS 5 vs. 6, due to the specific SQLite versions included in each distribution.
A final thought, from the realm of intuition: if I were targeting heavily concurrent access to a database (subjective, yes), I'd consider replacing SQLite with some other engine. SQLite is a great tool for many purposes, but concurrent access is not its strong point (see https://www.sqlite.org/lockingv3.html).
Cheers,
--
exvito
More information about the Twisted-Python
mailing list