-
Notifications
You must be signed in to change notification settings - Fork 11.3k
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
[11.x] Add ability to configure SQLite busy_timeout
, journal_mode
, and synchronous
pragmas
#52052
Conversation
busy_timeout
busy_timeout
, journal_mode
, and synchronous
pragmas
Excuse my ignorance, but aren't we supposed to set |
Yeah good question, I addressed that in my notes above. We can just set it once but I don't know if we're necessarily "supposed to." I'm assuming that the overhead of setting it to the same value repeatedly is completely negligible but I can do some more research, I haven't seen any mention of that being an issue and it's what Rails currently does. I figured keeping the code here simple and consistent was more important. |
And actually it's only |
@bakerkretzmar Am I missing something?
I run migrations, check the mode and it returns delete.
EDIT: Forget it, someone cached my config locally |
I am getting error
When I comment those settings, no error. Error appears when running How is this merged without testing @taylorotwell @bakerkretzmar |
This PR adds optional
busy_timeout
,journal_mode
, andsynchronous
configuration options to allow setting the corresponding pragmas on SQLite database connections. Together, these three configuration options can improve SQLite's performance enormously.Background
This SQLite configuration:
is becoming the widely recommended default for modern apps because it is orders of magnitude faster than the default setup and far less prone to
SQLITE_BUSY
errors.journal_mode
configures how transactions are implemented. The default setting,DELETE
, uses a rollback journal. Since SQLite 3.7 aWAL
mode is available that uses a write ahead log, which is significantly faster and allows concurrent database reads and writes in more scenarios.busy_timeout
configures how long SQLite will wait when a table is locked before returning aSQLITE_BUSY
error. The default is0
, which means any attempted concurrent writes will fail immediately. Setting it to a positive integer will make SQLite wait that many milliseconds if the database is locked, which in most cases means that operations will complete with a negligible delay instead of erroring.synchronous
configures how often SQLite flushes the contents of the database to the disk. The default,FULL
, writes data to disk more or less immediately when it changes. TheNORMAL
mode syncs data when necessary but less often, and in combination with WAL mode is much faster, fully consistent, and highly durable.NORMAL
is SQLite's recommended setting when used with WAL mode.Rails and Django both currently support some or all of this functionality. They both have a
timeout
configuration option, Rails 7.1 defaults to WAL mode and NORMAL, and Django 5.1 (releasing in August) is going to add configuration fields for setting transaction modes and other custom pragmas:More info:
Implementation
I based this on the existing code for setting the
foreign_keys
pragma, it works exactly the same way except that the new options accept custom values instead of just being on or off.busy_timeout
andsynchronous
are per-connection settings and have to be set every time Laravel connects to a SQLite database (like the existingforeign_keys
pragma), so it makes sense to store them in the config likeforeign_keys
.journal_mode
is a persistent setting and technically only has to be set once, but the implementation is much simpler and more consistent if we just set it on every connection too.The new configuration options all default to
null
so that existing apps will be completely unaffected by this change.Alternatives
How I'm currently doing this:
Future Scope
I'm going to work on a PR for immediate transactions too, which also combine really well with these settings but will have to be implemented differently.