Skip to content
Advertisement

Why doesn’t SQLite appear to lock my table / row?

I’m tinkering with an in-memory sqlite database, trying to wrap my head around concurrency. Here’s an example using SQLAlchemy

OUTPUT

Here, I use two connections to write data to the same record. I would expect the output to be “A112”, because I thought the first connection would have a lock on the record until it COMMITs, but to my surprise the output is “A121”.

Does SQLite actually not lock the table or am I misunderstanding what’s happening? (Would I get the same result with another database like PostgreSQL?)

Advertisement

Answer

I’d actually expect the code to error out if you have multiple connections since you’re creating a deadlock. You’re running into an implementation quirk of SQLAlchemy.

From the documentation:

class sqlalchemy.pool.SingletonThreadPool(creator, pool_size=5, **kw)

A Pool that maintains one connection per thread.

[…]

SingletonThreadPool is used by the SQLite dialect automatically when a memory-based database is used.

In other words, when you open a :memory: database, rather than using SQLite’s shared cache mode that would enable sharing a memory database between different connections, SQLAlchemy creates a single connection and funnels all connections objects through it.

You can see the same behavior on a file connection by passing poolclass=SingletonThreadPool to create_engine, or you can see the error with a memory database using multiple connections to the same database outside of SQLAlchemy:

User contributions licensed under: CC BY-SA
6 People found this is helpful
Advertisement