あるプロセスが データを書き換え中に、他のプロセスが書き換えできないようになっているようだ。
仕組みとしては、トランザクション中に、他のプロセスがトランザクションを開始しようとすると、SQLITE_BUSY ってのが返ってくる。 API の sqlite_busy_timeout() を使って、SQLITE_BUSY になるまでの時間をミリ秒で指定できる。
トランザクションの開始だけでなく、DELETE, INSERT, UPDATEなども出来ないようになっている。
pysqlite を使って実験(Python)
別のプロセスでトランザクション状態にしておく。(例: sqlite コマンドを使って、BEGIN; を実行しておく)
以下の Python スクリプトを実行する。タイムアウトは10秒(10000ミリ秒)
import sqlite
con = sqlite.connect("test.db", timeout=10000)
try:
cursor = con.cursor()
cursor.execute("DELETE FROM test")
print "Succeeded"
except sqlite.OperationalError, errmsg:
print errmsg
con.close()
実行結果
- 別プロセスがトランザクション中にスクリプトを実行
10秒ほど待ってから、database is locked のメッセージが表示される。(errmsg に database is locked が設定された。)
- 別プロセスがトランザクションを終了してからスクリプトを実行
すぐに終了し、Succeeded のメッセージが表示される
- 別プロセスがトランザクション中にスクリプトを実行。10秒のタイムアウトまでに、別プロセスのトランザクションが終了
別プロセスのトランザクションが終了後すぐに、Python スクリプトが終了し、Succeeded のメッセージが表示される
libsqlite.a を使って確認(C言語)
先程の Python スクリプトのように、ロック状態を確認するプログラムを C言語で組んでみた。
#include <stdio.h>
#include <sqlite.h>
int main(int argc, char *argv[])
{
sqlite *db;
char *errmsg;
int result;
int return_code;
/* SQLite データベースを OPEN */
db = sqlite_open("test.db", 0755, &errmsg);
if (!db) {
printf("%s: %s\n", argv[0], errmsg);
return 30;
}
/* 検索を開始 */
sqlite_busy_timeout(db, 10000);
result = sqlite_exec(db, "DELETE FROM test WHERE id > 10000",
NULL, NULL, &errmsg);
switch (result) {
case SQLITE_OK:
printf("Succeeded\n");
return_code = 0;
break;
case SQLITE_BUSY:
/* The database file is locked */
printf("SQLITE_BUSY\n");
return_code = 10;
break;
case SQLITE_LOCKED:
/* A table in the database is locked */
printf("SQLITE_LOCKED\n");
return_code = 20;
break;
default:
printf("Unknown error\n");
return_code = 100;
break;
}
sqlite_close(db);
return return_code;
}
新しいコメントの投稿