Caught ActiveRecord::StatementInvalid: SQLite3::BusyException: database is locked: SQL
ActiveRecord で SQLite3 を利用していた場合に以下のエラーが発生しました。
Caught ActiveRecord::StatementInvalid: SQLite3::BusyException: database is locked: SQL /usr/local/lib/ruby/gems/1.8/gems/activerecord-2.0.2/lib/active_record/connection_adapters/abstract_adapter.rb:150:in `log' /usr/local/lib/ruby/gems/1.8/gems/activerecord-2.0.2/lib/active_record/connection_adapters/sqlite_adapter.rb:132:in `execute' /usr/local/lib/ruby/gems/1.8/gems/activerecord-2.0.2/lib/active_record/connection_adapters/sqlite_adapter.rb:345:in `catch_schema_changes' /usr/local/lib/ruby/gems/1.8/gems/activerecord-2.0.2/lib/active_record/connection_adapters/sqlite_adapter.rb:132:in `execute' /usr/local/lib/ruby/gems/1.8/gems/activerecord-2.0.2/lib/active_record/connection_adapters/sqlite_adapter.rb:256:in `select' /usr/local/lib/ruby/gems/1.8/gems/activerecord-2.0.2/lib/active_record/connection_adapters/abstract/database_statements.rb:7:in `select_all_without_query_cache' /usr/local/lib/ruby/gems/1.8/gems/activerecord-2.0.2/lib/active_record/connection_adapters/abstract/query_cache.rb:55:in `select_all'
原因は、SQLite3 のファイルに同時にアクセスした場合に、ロックが競合していたためでした。
対策は、ActiveRecord を継承しているクラスでタイムアウトを設定することです。
以下の場合 10,000(ミリ秒) 待ちます。
ActiveRecord::Base.establish_connection( :adapter => 'sqlite3', :database => '/hoge/var.sqlite3', + :timeout => 10000 )