1. 問題の原因
MySQL の公式ドキュメントでは、ネストされたトランザクションはサポートされていないと明確に述べられています:
1. トランザクションはネストできません。これは、START TRANSACTION ステートメントまたはそのシノニムの 1 つを発行するときに、現在のトランザクションに対して実行される暗黙的なコミットの結果です。
しかし、複雑なシステムを開発する場合、たとえば、関数 A が関数 B を呼び出し、関数 A がトランザクションを使用し、関数 B もトランザクション内で呼び出されることになります。 , そのため、トランザクションのネストが発生します。この時点では、A の事柄は実際にはほとんど重要ではありません。なぜですか。上記の文書で言及されており、簡単に翻訳すると次のようになります:1. START TRANSACTION 命令を実行すると、暗黙的にコミット操作が実行されます。 したがって、システム アーキテクチャ レベルでトランザクションのネストをサポートする必要があります。
幸いなことに、doctrine や laravel など、一部の成熟した ORM フレームワークはネストをサポートしています。次に、これら 2 つのフレームワークがどのように実装されているかを見てみましょう。これら 2 つのフレームワークにおける関数と変数の名前付けは比較的直感的ですが、名前を付けることで関数や変数の意味を直接知ることができるので、一見しただけではそれほど混乱する必要はありません。とても怖かったです:)
2. ドクトリンの解決策
まず、Doctrine でトランザクションを作成するコードを見てみましょう (無関係なコードは削除されました):
[php] プレーンコピーを表示
処理方法も非常に単純で、レベルが 1 の場合は、前のセーブポイントに戻るかどうかを直接ロールバックします。
[php] プレーンコピーを表示
算了,不费口舌解释段了吧 :)
三、laravel の解決方法laravel の処理方法は、相対的に荒々しい暴挙であり、以下の構築業務の操作:
[php] プレーンコピーを表示
感觉どうやって?とても簡単です?先判断当前有几个事务、如果是第一、ok、事务開始、否则就啥都不做、那么是啥是啥都不做呢?继续往下看ロールバック的操作:
[php] プレーンコピーを表示