Skip to content

introduce default_transaction_mode option #308

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

Merged
merged 2 commits into from
Nov 4, 2024

Conversation

egze
Copy link
Contributor

@egze egze commented Nov 3, 2024

Following the discussion elixir-sqlite/ecto_sqlite3#153, the PR introduces a default_transaction_mode.

The benefit is to configure it once if this is the common usage pattern for your application.

Research shows that a recommended setting for most web application is to set transaction more to immediate.

Here are 2 convincing sources:

https://fractaledmind.github.io/2024/04/15/sqlite-on-rails-the-how-and-why-of-optimal-performance/

The author did extensive testing with Rails and concluded that it is not viable to have DEFERRED in a typical Rails application. And to me a typical Rails application has the same usage pattern as a Phoenix application.
In a context where you only have one connection or you have a large amount of transactions that only do read operations, this is great for performance, because it means that SQLite doesn’t have to acquire a lock on the database for every transaction, only for transactions that actually write to the database. The problem is that this is not the context Rails apps are in. In a production Rails application, not only will you have multiple connections to the database from multiple threads, Rails will only wrap database queries that write to the database in a transaction. And, when we write our own explicit transactions, it is essentially a guarantee that we will include a write operation. So, in a production Rails application, SQLite will be working with multiple connections and every transaction will include a write operation. This is the opposite of the context that SQLite’s default deferred transaction mode is optimized for.

https://highperformancesqlite.com/watch/transaction-modes

Aaron Francis is a well known database expert and his sqlite course is amazing. Here are some quotes:
So on the application side, whenever you connect to the database, you're going to want to set your transaction mode to immediate.
You'll need to look up for your specific framework how to connect to the database and how to make sure that all of the rights are wrapped in a begin immediate transaction. Most web frameworks wrap the rights in a transaction regardless, and so you're looking for the thing where you can set, alright, we want that to be an immediate transaction. I think the rails adapter for SQLite, I think that does that by default. I know in PHP, you can set a pdo attribute to set it to immediate. So you'll have to do a little bit of digging.

@warmwaffles warmwaffles merged commit d937a12 into elixir-sqlite:main Nov 4, 2024
9 checks passed
@egze egze deleted the default_transaction_mode branch November 4, 2024 06:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants