RailsでSQLite3 の lock timeout が発生したので少し調べて見ました。
(原因は複数transactionが発生してロックかかってただけです)
まずは
みんな大好きstackoverflow。
ruby on rails - SQLite3::BusyException - Stack Overflow
一時的な対策ではあるが、 database.yml の timeout 値を変更することでBusyExceptionsを減らすことができるかもねという記載があります。
ソースを見て見ます
activerecord
# activerecord-5.0.2/lib/active_record/connection_adapters/sqlite3_adapter.rb:30 db = SQLite3::Database.new( config[:database].to_s, results_as_hash: true ) db.busy_timeout(ConnectionAdapters::SQLite3Adapter.type_cast_config_to_integer(config[:timeout])) if config[:timeout]
SQLite3のbusy_timeout を呼んでいるだけのようです。
sqlite3
# sqlite3-1.3.13/lib/sqlite3/pragmas.rb def busy_timeout=( milliseconds ) set_int_pragma "busy_timeout", milliseconds end
set_int_pragma に値を渡しているだけ。
def set_int_pragma( name, value ) execute( "PRAGMA #{name}=#{value.to_i}" ) end
PRAGMA〜 という文字列で実行しているだけでした。
PRAGMAステートメント
全く知らなかったのですが、SQLite3固有の拡張コマンドでした。
busy_timeout は以下。
Pragma statements supported by SQLite
他にもcache sizeを変更したり同期タイミング(default_synchronous)を変更することで50倍以上高速になるそうです。
色々チューニングできそうです。