PHP5.2 x Postgres8.xのトランザクションについて


Postgresのトランザクションについて調べると、トランザクションを開始
した場合、ロールバック、もしくはコミットをするか、設定値の時間が
経過しないとトランザクションは終了しない。となっていました。
確かに、コンソール上で、Postgresを操作すると、上記のような動作に
なっていることを確認しましたが、PHPのスクリプト上でトランザクションを
実行すると、少し違う動きをするようでした。

例えば、下記のような場合、exitした時点でトランザクションが終了していました。
本来であれば、exitする前にロールバックする処理をいれるべきなのかと思いましたが
この場合は特になにもしないでよいのでしょうか。
---
$mdb2->beginTransaction();

$sql = "SELECT * FROM test WHERE id = ? FOR UPDATE";
$res = $mdb2->execute(array("100"));
$status = $res->fetchOne("status");

// ↓エラーが起きた場合。ここにロールバックする処理は入れない?
if (!$status) {
header("Location: http://errorerrorerror")
exit;
}

// ここにtestテーブルをUPDATEする処理など

$mdb2->commit();
?>

皆さんはどうされているのか知りたくて質問しました。
よろしくお願いします。


回答の条件
  • 1人5回まで
  • 登録:
  • 終了:2012/05/03 15:00:06
※ 有料アンケート・ポイント付き質問機能は2023年2月28日に終了しました。

回答3件)

id:mario-16 No.1

回答回数219ベストアンサー獲得回数21

ポイント100pt

もう御自身で納得されておるようですが参考になるかと思い回答させていただきます。

私は癖としてコミットとロールバックは必ず書くようにしています。
今回の場合はPDOというライブラリはクローズ時のデフォルトの挙動がロールバックになっていることとSQLが検索だけだったため特に問題はありません。

ですがデフォルトの処理を当てにする癖をつけていると以下のような場合に問題に遭遇する可能性があります。
・別のライブラリや言語を使った場合に嵌まる可能性がある
・処理が長くなりソースを分割した場合にSQL文とコネクションをクローズするところが離れていて更新系のSQLだということに気がつかない可能性
・DBによってはクローズ時に自動でコミットするものがある


明にコミットもしくはロールバックの処理が書かれていないソースを見ると何かおかしいと思うようにしておいた方が良かろうかと思います。

id:jayz

回答ありがとうございます。

やはり、自動でロールバックされるとはいえ、明示的にスクリプト内でロールバック
させた方がぐっすり眠れそうですね。

ただ、現在PEAR MDB2を使ってDBを操作していますが、エラーの処理をエラーハンドラ
関数を指定してまとめて行なっています。
その関数内でMDB2オブジェクトをグローバル宣言することで、トランザクション中か
確認できますが、MDBオブジェクトを生成していない場合でも、この関数を通る場合
があります。

その場合、!empty($mdb2) && $mdb2->isTransaction()のようにすることで、簡易的?
にデータベースに接続済みなのか判定できますが、より正確な判断ができないものかと
悩みます。

2012/04/27 05:48:19
id:taroe No.2

回答回数1099ベストアンサー獲得回数132

ポイント100pt

$mdb2->beginTransaction();

このように明示的にトランザクションの開始を宣言する
プログラムスタイルでは
通常は、コミットもロールバックもきちんと書くのが普通です。


設定によっては、トランザクションの開始を書かなくて良い場合があり
その場合は、コミットの時だけ明示的に書き、ロールバックの場合は書かないという
スタイルが多いです。


>その場合、!empty($mdb2) && $mdb2->isTransaction()のようにすることで、簡易的?

MDBオブジェクトを生成してるかどうかの判断は必要だと思いますが、
トランザクションを開始していない状態で
ロールバックをしても、問題ないはずですけどね。

トランザクションが開始されてるかどうかのチェックのが普通だとは思えないです。

id:oil999 No.3

回答回数1728ベストアンサー獲得回数320

ポイント100pt

トランザクション宣言しているのであれば、正常系ではコミットを、異常系ではロールバックすべきです。
ご質問にあるソースでは、exit() する前にロールバック処理を入れましょう。

  • id:jayz
    あぁ、これか...
    「スクリプトが終了したり接続が閉じられようとした際に、もし処理が 完了していないトランザクションがあれば PDO が自動的に ロールバックします。これは、スクリプトが予期せぬ状態で終了した場合に データの不整合が発生するのを避けるための安全装置です。もし 明示的にコミットしていなければ、おそらく何かおかしなことが 起こったのだろうと推測されます。そのため、データを守るために ロールバックが行われるのです。」
    http://php.net/manual/ja/pdo.transactions.php

この質問への反応(ブックマークコメント)

「あの人に答えてほしい」「この質問はあの人が答えられそう」というときに、回答リクエストを送ってみてましょう。

これ以上回答リクエストを送信することはできません。制限について

回答リクエストを送信したユーザーはいません