0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Doctrine Transaction Unexpected Nesting Level Increasing

Last updated at Posted at 2019-04-11

#作業環境
PHP5.3 + Fuel 1.8.1 + Doctrine

#問題
業務上、1つのトランザクションの中に、下記のPseudoコードの感じで処理を実行し、最後纏めてコミットしたい。

$em = \Fuel\Doctrine::manager("default");
$em->getConnection()->beginTransaction();
…
DB登録処理呼び出し関数1($em);
DBクエリ処理呼び出し関数1($em);
繰り返し処理{
…
    DB登録処理呼び出し関数2($em);
    DB更新処理呼び出し関数1($em);
…
}
…
DB更新処理呼び出し関数2($em);
$em->commit();

が、コミットはどうしても成功せず、3日を悩まされました。

#調査経過
たまたま、Doctrineトランザクション管理のNestingレベルを見ようとして、
Doctrineトランザクション公式参照⇒https://www.doctrine-project...

⇓をDB変更や登録関数の実行前後に貼って、驚きの結果がわかりました。
echo "TransactionNestingLevel Before Insert :".$em->getConnection()->getTransactionNestingLevel()."\n";

繰り返し処理の中で、Nestingレベルの数値がどんどん上がる!!!

TransactionNestingLevel Before Insert :11
TransactionNestingLevel After Insert :11
TransactionNestingLevel Before Insert :41
TransactionNestingLevel After Insert :41
TransactionNestingLevel Before Insert :215
TransactionNestingLevel After Insert :215
TransactionNestingLevel Before Insert :301
TransactionNestingLevel After Insert :301
TransactionNestingLevel Before Insert :345
TransactionNestingLevel After Insert :345
TransactionNestingLevel Before Insert :395
TransactionNestingLevel After Insert :395
TransactionNestingLevel Before Insert :461
TransactionNestingLevel After Insert :461

Are you kidding me!!なんじゃと

トランザクション階層が461階層に⇓

トランザクション階層1
    トランザクション階層2
        トランザクション階層3
                    …
                                        トランザクション階層461

変更をDBに反映するために、$em->commit();を__460__回実行せよ!!だからコミットできないか!
なんじゃと

待って!今回操作対象データが230件。最後に461件というのは、230の2倍がプラスされたんじゃないか?都合がいい数値に手がかりがありそう!!

いろいろ実験を経て、下記の感じのコードを実行すると、不具合の箇所が特定できました。

$em = \Fuel\Doctrine::manager("default");
$em->getConnection()->beginTransaction();
echo "TransactionNestingLevel beginTransaction:".$em->getConnection()->getTransactionNestingLevel()."\n";
$info = array();
$info[0] = array(
    "Sequence"=>5
    …
);
$info[1] = array(
    "Sequence"=>6
    …
);
echo "TransactionNestingLevel After Setting array :".$em->getConnection()->getTransactionNestingLevel()."\n";

結果:

TransactionNestingLevel beginTransaction :1
TransactionNestingLevel After Setting array :3

#結論

__配列代入処理が一回実行で、DoctrineのトランザクションNestingレベルが1 Plusされる__ことが分かりました。だからか!前230件の2倍Plusされるのも、登録関数が呼ばれる前に、データを配列で渡すために、配列代入処理を2回実施しましたからです。

わけわからねぇ!!!!!

なんじゃと

#対策
はい!退避策として、繰り返し処理の中のDB変更処理を全部外に出して、$em->getConnection()->setAutoCommit(false);で、繰り返し処理でPlusされたトランザクションレベルを1に戻した。

$em = \Fuel\Doctrine::manager("default");
$em->getConnection()->beginTransaction();
…
DB登録処理呼び出し関数1($em);
DBクエリ処理呼び出し関数1($em);
繰り返し処理{
…
…
}
…
$em->getConnection()->setAutoCommit(false);
DB登録処理呼び出し関数2($em);
DB更新処理呼び出し関数1($em);
…
DB更新処理呼び出し関数2($em);
$em->commit();

こんなつまらないことで、3日間が蒸発した!!!
死ね

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?