-
Notifications
You must be signed in to change notification settings - Fork 11.6k
[11.x] Add ability to configure SQLite busy_timeout, journal_mode, and synchronous pragmas
#52052
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
Conversation
busy_timeoutbusy_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, andsynchronousconfiguration 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_BUSYerrors.journal_modeconfigures how transactions are implemented. The default setting,DELETE, uses a rollback journal. Since SQLite 3.7 aWALmode is available that uses a write ahead log, which is significantly faster and allows concurrent database reads and writes in more scenarios.busy_timeoutconfigures how long SQLite will wait when a table is locked before returning aSQLITE_BUSYerror. 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.synchronousconfigures 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. TheNORMALmode syncs data when necessary but less often, and in combination with WAL mode is much faster, fully consistent, and highly durable.NORMALis 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
timeoutconfiguration 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_keyspragma, it works exactly the same way except that the new options accept custom values instead of just being on or off.busy_timeoutandsynchronousare per-connection settings and have to be set every time Laravel connects to a SQLite database (like the existingforeign_keyspragma), so it makes sense to store them in the config likeforeign_keys.journal_modeis 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
nullso 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.