小さい頃はエラ呼吸

いつのまにやら肺で呼吸をしています。


PHP5とSQLite3でつくるトランザクション処理

PHP5とSQLite3でトランザクション処理を行うサンプルプログラムをつくってみました。
SQLite3でもトランザクション処理の考え方は、他のデータベースと変わりません。トランザクションを開始して、正常に終了したらコミットして、エラーがあれば、ロールバックする。これだけです。

トランザクション処理のサンプルコード

以下の例では、はじめにデータを挿入(insert)して、その後で更新(update)しています。更新処理では、わざとSQLの文法エラーが発生するようにして、ロールバックされるようにしています。
エラーになったときに、挿入(insert)したデータが消えていれば、正しくロールバックされていることが確認できます。

try {
  // トランザクションの開始
  $db->exec("BEGIN DEFERRED;");
  
  // insert
  $sql = "INSERT INTO hoge (name) VALUES('" . $name . "');";
  $db->exec($sql);
  
  // update(わざとエラーになるようにしています)
  $sql = "UPDATE hoge S'ET NAME = 'hoge';";
  if(!$db->exec($sql)) {
    // ロールバック
    $db->exec("ROLLBACK;");
    print 'SQLの実行でエラーが発生しました。<br>';
    return;
  }
  
} catch (Exception $e) {
  // ロールバック
  $db->exec("ROLLBACK;");
  print 'SQLの実行でエラーが発生しました。<br>';
  print $e->getTraceAsString();
  return;
}

// コミット
$db->exec("COMMIT;");
SQLite3の排他制御について

BEGINコマンドを発行した場合、デフォルトではBEGIN DEFERREDというトランザクションが開始されます。

BEGIN DEFERRED(既定 ver3.0.8〜):
INSERT、UPDATE、DELETEなどの更新系コマンドが実行されるまでロックがかからず、それまでは他ユーザからの読み書きが可能。
SQLite はてなブックマーク - SQLite

ちなみに、SQLite3ではトランザクションの宣言がなくても、更新系SQLが発行される場合には、自動的にトランザクションが開始されるようです。

トランザクションが宣言されなかった場合でも、データを更新するコマンドが実行されるときには自動的にトランザクションが宣言される。
SQLite はてなブックマーク - SQLite

トランザクションを宣言しないと遅くなる

上記のように、SQLite3ではトランザクション宣言をしなくても自動的にトランザクションが開始されます。しかしながら、トランザクションの宣言がない場合、更新系処理が極端に遅くなるという特性があるようです。したがって、更新処理を行う場合にはトランザクションの宣言を省略しないほうが良いです。

更新系(INSERT/UPDATE/DELETE)のSQLをトランザクションブロックなしで発行すると、動作が遅くなるという特性がある。 SQLiteではロック問題を別にしても、更新系のSQLはBEGIN〜COMMITで囲むことが望ましい。
SQLite はてなブックマーク - SQLite

比較方法には問題があると思うけど、トランザクションを使った方が明らかに早い。不使用の35倍の早さですからね・・・圧倒的です。件数が多くなるほど、この差が開きそうだ。
トランザクションを使ってSQLiteの処理を超高速化 | KUMALOG はてなブックマーク - トランザクションを使ってSQLiteの処理を超高速化 | KUMALOG