Replies: 11 comments 5 replies
|
There are a few built-in options for busy handlers
@fractaledmind has written a few blog posts on this topic, e.g. https://fractaledmind.github.io/2024/01/11/sqlite-in-ruby-non-blocking-timeout/ if that's interesting. |
|
@flavorjones: Thanks for reaching out and pointing to available options. Some followup-questions:
SQLite3::Database.open('db', busy_handler: lambda { |e| puts e; sleep 1; true })
SQLite3::Database.open('db', busy_timeout: 1000)
SQLite3::Database.open('db', busy_handler_timeout: 1000)
|
|
@flavorjones: Still need a hand here. Puzzled why running two simple connections to the same db breaks so easily. |
|
I can't reproduce what you're describing in your OP. I'm using sqlite3 v2.0.2 (precompiled x86_64-linux-gnu) on linux and |
|
Thanks for confirming. Will try to pinpoint the issue. |
|
@flavorjones: Can you reproduce this? (I'm on macOS 14.5) $ sqlite3 hello
sqlite> create table foo (bar);
sqlite> insert into foo values (1);irb(main):001> db = SQLite3::Database::open('hello', busy_timeout: 1000)
irb(main):002> db.query('select * from foo where bar = ?', [1]).any?
=> trueAnother shell: irb(main):001> db = SQLite3::Database::open('hello', busy_timeout: 1000)
irb(main):002> db.query('insert into foo values (?)', [1])
/opt/homebrew/lib/ruby/gems/3.3.0/gems/sqlite3-2.0.2-arm64-darwin/lib/sqlite3/statement.rb:84:in `step': database is locked (SQLite3::BusyException) |
|
Yes, I can reproduce that. Setting journal mode to WAL will allow you to have reads concurrent with writes. See @fractaledmind's excellent blog post on configuring SQLite3 for concurrent access here: https://fractaledmind.github.io/2023/09/07/enhancing-rails-sqlite-fine-tuning/ And the SQLite docs themselves: https://www.sqlite.org/pragma.html#pragma_locking_mode |
|
OK, this is actually quite simple. Assuming what happens:
Now, collision does not occur if removing Questions:
|
|
@flavorjones: I really appreciate this clarification. You're right. One assumes a project maintainer is God and knows everything. I'll take this incident as a reminder that this might -- and should necessarily -- not be the case. |
|
@fractaledmind: Could you reply to the posting above ("OK, this is actually quite simple...") |
|
@flavorjones + @fractaledmind + @oldmoe: OK, the solution is actually quite obvious. If a ResultSet is not going to be iterated, it must be closed, lest the database is locked forever waiting for iteration that never comes. If one never does iteration after refine SQLite3::ResultSet do
def any?
super.tap(&:close)
end
endCould the API be changed or extended in accordance? Note: Updated code example to return the object as expected |
Uh oh!
There was an error while loading. Please reload this page.
Referring to #261, etc. is
SQLite3::BusyExceptionwarranted and unavoidable, even if hitting up the database from two different processes, as opposed to two threads in the same process?sqlite> create table foo (bar);Is there no way around everyone having to write their own busy handler?
Or use Write-Ahead Logging?
All reactions