ホームページ  >  記事  >  バックエンド開発  >  PHP で MySQL ネストされたトランザクションを実装するための 2 つのソリューション、mysql namesting_PHP チュートリアル

PHP で MySQL ネストされたトランザクションを実装するための 2 つのソリューション、mysql namesting_PHP チュートリアル

WBOY
WBOYオリジナル
2016-07-13 09:55:55941ブラウズ

PHP で MySQL ネストされたトランザクションを実装するための 2 つのソリューション、mysql ネスト

1. 問題の原因

MySQL の公式ドキュメントでは、ネストされたトランザクションはサポートされていないと明確に述べられています:

1. トランザクションはネストできません。これは、START TRANSACTION ステートメントまたはそのシノニムの 1 つを発行するときに、現在のトランザクションに対して実行される暗黙的なコミットの結果です。

しかし、複雑なシステムを開発する場合、たとえば、関数 A が関数 B を呼び出し、関数 A がトランザクションを使用し、関数 B もトランザクション内で呼び出されることになります。 , そのため、トランザクションのネストが発生します。この時点では、A の事柄は実際にはほとんど重要ではありません。なぜですか。上記の文書で言及されており、簡単に翻訳すると次のようになります:

1. START TRANSACTION 命令を実行すると、暗黙的にコミット操作が実行されます。 したがって、システム アーキテクチャ レベルでトランザクションのネストをサポートする必要があります。

幸いなことに、Doctrine や Laravel など、一部の成熟した ORM フレームワークではネストがサポートされています。次に、これら 2 つのフレームワークがどのように実装されているかを見てみましょう。これら 2 つのフレームワークにおける関数と変数の名前付けは比較的直感的ですが、名前を付けることで関数や変数の意味を直接知ることができるので、一見しただけではそれほど混乱する必要はありません。とても怖かったです:)

2. ドクトリンの解決策

まず、Doctrine でトランザクションを作成するコードを見てみましょう (無関係なコードは削除されました):

[php] プレーンコピーを表示 ​
  1. /**  
  2. * 著者 http://www.lai18.com
  3. * 日付 2015-04-19
  4. * バージョン 1
  5. **/
  6. public functionbeginTransaction()
  7. {
  8. ++$this->_transactionNestingLevel
  9. } else
  10. if
  11. ($this->_nestTransactionsWithSavepoints) {
  12. されていない }
  13. }
  14. この関数の最初の行は、_transactionNestingLevel を使用して現在のネスト レベルを識別します。それが 1 の場合、つまりネストがまだない場合は、デフォルトのメソッドを使用して START TRANSACTION を実行します。それが大きい場合は問題ありません。 1 よりも、つまり、ネストがある場合、このセーブポイントは、ロールバックが必要な場合にのみ、このポイントまでロールバックできるトランザクション記録ポイントとして理解できます。次に、rollBack 関数を見てみましょう: [php] プレーンコピーを表示  
    1. 1. /**  
    2. * 著者 http://www.lai18.com
    3. * 日付 2015-04-19
    4. * バージョン 1
    5. **/
    6. public function rollBack()
    7. {
    8. if ($this->_transactionNestingLevel == 0) {
    9. throw ConnectionException::noActiveTransaction();  
    10. }
    11. if ($this->_transactionNestingLevel == 1) {
    12. $this->_transactionNestingLevel = 0;  
    13. $this->_conn->rollback();  
    14. $this->_isRollbackOnly = false;  
    15. } else if ($this->_nestTransactionsWithSavepoints) {
    16. $this->rollbackSavepoint($this->_getNestedTransactionSavePointName());  
    17. --$this->_transactionNestingLevel;  
    18. } else {
    19. $this->_isRollbackOnly = true;  
    20. --$this->_transactionNestingLevel;  
    21. }
    22. }

    処理方法も非常に単純で、レベルが 1 の場合は、前のセーブポイントに戻るかどうかを直接ロールバックします。

    [php] プレーンコピーを表示  

    1. 1. /**  
    2. * 著者 http://www.lai18.com
    3. * 日付 2015-04-19
    4. * バージョン 1
    5. **/
    6. public function commit()
    7. {
    8. if ($this->_transactionNestingLevel == 0) {
    9. throw ConnectionException::noActiveTransaction();  
    10. }
    11. if ($this->_isRollbackOnly) {
    12. throw ConnectionException::commitFailedRollbackOnly();  
    13. }
    14. if ($this->_transactionNestingLevel == 1) {
    15. $this->_conn->commit();  
    16. } else if ($this->_nestTransactionsWithSavepoints) {
    17. $this->releaseSavepoint($this->getNestedTransactionSavePointName());  
    18. }
    19. --$this->_transactionNestingLevel;  
    20. }

    算了,不费口舌解释段了吧 :)

    三、laravel の解決策laravel の処理方法相対的单荒暴一部、我们先来看下创建事务的操作:

    [php] プレーンコピーを表示 ​
    1. 1.
    2. /**  
    3. * 著者 http://www.lai18.com
    4. * 日付 2015-04-19
    5. * バージョン 1
    6. **/
    7. public functionbeginTransaction()
    8. {
    9. ++$this->トランザクション
    10. }
    11. }
    12. どう感じますか?とても簡単ですよね?まず、現在存在するトランザクションの数を確認します。それが最初のトランザクションである場合、トランザクションは開始されます。それ以外の場合、何も行われないのはなぜでしょうか。引き続き、rollBack の操作を確認してください:
    13. [php] プレーンコピーを表示 ​
      1. 1. /**  
      2. * 著者 http://www.lai18.com
      3. * 日付 2015-04-19
      4. * バージョン 1
      5. **/
      6. パブリック 関数 rollBack()
      7. {
      8. _
      9. }
      10. }
      11. }
      12. わかりますか?現在のトランザクションが 1 つだけである場合にのみ、実際にロールバックされます。それ以外の場合は、カウントが 1 つだけデクリメントされます。これが、Laravel の処理が比較的単純で粗雑であると述べた理由です。実際には、ネストされた内側の層には実際のトランザクションは存在しません。最も外側の層には全体的なトランザクションがあるだけです。しかし、これによって問題も解決されます。内部層が新しいトランザクションを作成すると、コミットの問題が発生します。原則は次のとおりです。完全を期すために、コミット コードもコピーしてください。
      13. [php]
      14. プレーンコピーを表示 ​ パブリック 関数
      15. commit()
      16. {

        }
      1. http://www.bkjia.com/PHPjc/991536.htmlwww.bkjia.comtru​​e
      2. http://www.bkjia.com/PHPjc/991536.html技術記事
      3. PHP で MySQL のネストされたトランザクションを実装するための 2 つのソリューション、mysql ネスト 1. 問題の原因は、MySQL の公式ドキュメントで、ネストされたトランザクションがサポートされていないと明確に述べられています。 1. トランザクションを n...
声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。