テーブルロック時のSQLITE_BUSY(5)
SQLite3ではトランザクションによってテーブルロックがかかっている場合、そのテーブルを更新しようとするとSQLITE_BUSY(5)が発生する。
SQLITE_BUSY(5)については以下を参照。 www.sqlite.org
対処法
この問題について、SQLite3ではsqlite3_busy_timeout
を実行してタイムアウトまでの時間をセットすることで自動的にリトライしてくれる機能があり、これで回避することができる。
sqlite3_busy_timeout
については以下を参照。
www.sqlite.org
トランザクション中に更新処理を行うと発生するSQLITE_BUSY(5)
BEGIN DEFERRED
でトランザクションを開始した場合に発生する。SQLite3ではトランザクションに以下の2種類あり、BEGIN DEFERRED
では最初に実行したSQLがSELECTなどのread系の場合はread transactionとして開始される。
タイプ | 説明 |
---|---|
read transaction | 読み込み専用。 他のスレッド等から更新を行うことができる。トランザクション中はそれらの更新は見えず、更新前のデータが参照される。 |
write transaction | 読み書き可能。 他のスレッド等から更新を行うことはできない。 |
その後、UPDATEなどのwrite系のSQLが実行されるとwrite transactionに切り替えられるが、その際、別のスレッド等がすでにデータベースを更新していると切り替えに失敗し、SQLITE_BUSY(5)が発生する。このエラーはsqlite3_busy_timeout
では対応してくれない。また通常のSQLITE_BUSY(5)と異なり、リトライしても成功することは無い。
対処法
トランザクションの開始をBEGIN IMMEDIATE
に変更する。この場合、最初からwrite transactionとして開始されるので、この時点でテーブルがロックされる。他のスレッドが同時にテーブルを更新する可能性があるので、sqlite3_busy_timeout
を実行しておくことでそれらは自動的にリトライが行われる。
SQLite3のトランザクションについては以下を参照。 www.sqlite.org