2


1

トランザクションの動作に関する2つの簡単な質問

このようなコードがあります。

function foobar(array& $objects, $con = null)
{
   if (is_null($con))
      $con = DbSingleton::getConnectio();

   $con->beginTransaction();  // <- question 1

   try
   {
     foreach($objects as $object)
     {
        // allocate memory for new object
        $new_obj = new MyShiningNewObject();

        // do something to the new object ...
        $new_obj->setParentId($object->getId());
        $new_obj->save($con);

        // mark for garbage collection
        unset($new_obj);  // <- question 2
      }

     $con->commit();
  }
  catch(Exception $e){ $con->rollBack(); }
}

私の質問は:

  1. トランザクションを開始しています。これはネストされたトランザクションである可能性があります。 入れ子になったトランザクションの場合、例外がスローされてロールバックすると、ロールバックはどのくらい前に(最も外側のトランザクションに)行われますか?-常識的にはこれが当てはまるはずですが、誰にもわかりません。

  2. メモリを解放しています(OK、Zend GCで「解放可能」とマーク)。 から ループの後でトランザクションをコミットしています(変数はループ内でfrreableとしてマークされています)、これは安全ですか?値が由来する変数を設定解除したとしても、データはdbに安全に保存されますか?

2 Answer


2


一番外側のトランザクションの結果だけが外部から見えるため、ネストされたトランザクションはほとんど意味がなく、主要なシステムでは「SQL Server」のみがそれらをサポートします。

「SQL Server」では、中間ロールバックは中間トランザクションの先頭にロールバックし、中間コミットは何もしません。

最外部のロールバックは、最外部のトランザクション全体をロールバックし(間にコミットがあったとしても)、最外部のコミットは最外部のトランザクション全体をコミットします。

他のシステムのトランザクションレベルは1つだけで、その間に可能な「SAVEPOINTS」があります。 以前の各セーブポイントに(名前を指定して)ロールバックできますが、savenameポイントなしで「COMMIT」または「ROLLBACK」を発行すると、常に最も外側のトランザクションがコミットまたはロールバックされます。


1


質問2に答えるには:

  • クエリがデータベースに送信されると、PHPで行われること 変数はもう関係ありません

  • 影響を与えるのは、あなたがすることだけです 「コミット」または「ロールバック」。

  • つまり、PHP変数の設定を解除しても、 DB側のトランザクション/データ。

     +
    質問1について:
  • データベースシステムがネストされたトランザクションをサポートしている場合、 「内部」トランザクションでのコミット/ロールバックは、論理的にはその「内部」トランザクションでのみ動作する必要があります。

  • ただし、ネストされたトランザクションはすべてのDBMSでサポートされているわけではないことに注意してください- たとえば、MySQLは、覚えている限り、それらをサポートしていません。

  • 参考として、ネストされた参照に関する3つの質問_( おそらくもっとたくさんあります)_:

  • Nested postgresql 8.2のトランザクション?

  • Nested SQL Serverのトランザクション

  • Are MySQLでネストされたトランザクションは許可されますか?