SQLite のデータベースに対して、複数のプロセス、スレッドから同時にアクセスする可能性があるとします。
他のプロセスがトランザクション処理中で排他ロック (EXCLUSIVE LOCK) がかかっていると、SELECT や UPDATE の実行に失敗します。 具体的には SQLITE_BUSY というコードが返ってきます。
このコードが返ってきた場合は、適切な時間だけ wait してリトライするようにします。 あるいは、以下のようなユーティリティ関数を使うこともできます。
sqlite3_busy_timeout()– 対象となる API 呼び出しが BUSY だった場合に、指定したミリ秒だけ内部的に粘るようにする。それでもダメならSQLITE_BUSYを返すようにする。 → API ドキュメントsqlite3_busy_handler()– 対象となる API 呼び出しが BUSY だった場合に、指定したコールバックハンドラを呼び出すようにする。 → API ドキュメント
簡単なのは、sqlite3_busy_timeout() でタイムアウト時間を 3 秒くらいに設定する方法でしょうか。
これで、複数プロセスからの書き込みがあるデータベースに対しても、SQLITE_BUSY で問題が出ることはほとんどなくなるはずです。
// Set the default busy handler to retry for 1000ms so that we can omit retry code.
sqlite3_busy_timeout(db, 3000 /* ms */);ちなみに、1 つのデータベースに対して複数プロセスからの同時アクセスがある場合でも、読み込みアクセスだけであれば排他ロックではなく共有ロック(SHARED LOCK)がかけられるため、BUSY 状態にはなりません。