MySQLのネストされたトランザクションで発生する問題

MySQLのネストされたトランザクションで発生する問題

MySQL はネストされたトランザクションをサポートしていますが、それを実行する人は多くありません... 少し前に、MySQL のネストされたトランザクションの必要性について議論している外国人を見ました。 とても面白いですね。このネストされた奇妙な使用法が必要なシナリオはあるのでしょうか? 元 DBA の同僚と話をしたところ、MySQL のネストされたトランザクションはどのようなシナリオでも使用すべきではないことがわかりました。

では、MySQL のネストされたトランザクションを使用するとどのような問題が発生するのでしょうか?

mysql> ceshi から * を選択します。 
+------+ 
| いいえ | 
+------+ 
| 1 | 
+------+ 
セット内の 1 行 (0.00 秒) 
 
mysql> トランザクションを開始します。 
クエリは正常、影響を受けた行は 0 行 (0.00 秒) 
 
mysql> ceshi 値に挿入します(2); 
クエリは正常、1 行が影響を受けました (0.00 秒) 
 
mysql> トランザクションを開始します。 
クエリは正常、影響を受けた行は 0 行 (0.00 秒) 
 
mysql> ceshi 値に挿入します(3); 
クエリは正常、1 行が影響を受けました (0.00 秒) 
 
mysql> コミット; 
クエリは正常、影響を受けた行は 0 行 (0.00 秒) 
 
mysql> ロールバック; 
クエリは正常、影響を受けた行は 0 行 (0.00 秒) 


最後にロールバックしたのに、データには 1 2 3 と表示されました。当初、トランザクションがネストされた状態だったのに、最後にロールバックしたと誰もが考えていました。実際、私たちが期待する結果は、サブトランザクションが正常に実行され、外側のトランザクションの失敗がロールバックされることです。 しかし、そうではありません。最終結果は 1 2 3 です。

+-----+ 
| いいえ | 
+-----+ 
| 1 | 
| 2 | 
| 3 | 
+-----+ 

SQL インタープリターがトランザクションの開始を検出すると、コミットがトリガーされます... !!!

begin_1 sql_1 begin_2 sql_2 sql_3 commit_1 rollback_1 .

begin_2 を実行すると、sql_1 はすでにコミットされています。commit_1 を実行すると、sql_2 と sql_3 はすでにコミットされています。この時点で、ロールバックすると無駄になります...すでにコミットされているため、何をロールバックできますか...

前述したように、アーキテクチャではネストされたトランザクションを使用する人はほとんどいませんが、誤ってネストされることもあります。 Python プロジェクトを例に挙げてみましょう。まず、デコレータを使用してトランザクション パッケージを実装します。次に、データ処理関数 def a() と def b() がトランザクションにラップされます。これらはすべて単一のトランザクションであるため、単に a または b を使用するかどうかは問題ではありません。 ロジック内で a が b を呼び出すと、何が起こりますか? はい、トランザクションはネストされています...これはほとんどのビジネス開発者が遭遇する問題だと思います。

では、このリスクを回避するにはどうすればよいでしょうか? ロックすることができます... サブトランザクションを作成する前に、グローバル ロックを設定し、ロック ステータスを確認します...

Flask フレームワークを使用している場合は、flask g グローバル変数を使用できます。

Django フレームワークの場合は、スレッドローカルを使用してグローバル変数を使用できます。

tornado や gevent などの非同期 IO アーキテクチャの場合は、fd を使用してコルーチン変数を関連付けることができます。

@デコレータ
def with_transaction(f, *args, **kwargs):
 
  db = connection.get_db_by_table("*")
  試す:
    db.begin()
    ret = f(*args, **kwargs)
    コミット()
  を除外する:
    ロールバック()
    上げる
  リターン ret
 
 
@トランザクションあり
def hid(self):
  '''注文がアプリに表示されません'''
  self.status が OrderStatus.allow_deletion_statuses() にない場合:
    OrderStatusChangeNotAllowed(self.status, OrderStatus.deleted) を発生させます。
...
 
 
@トランザクションあり
def change_receipt_info(自分、住所、名前、電話番号):
  地域 = Region.get_by_address(アドレス)
  ...

次のステートメントを実行すると、トランザクションは強制的にコミットされます。もちろん、ここでの前提は autocommit = True です。

関数の変更  
手順の変更  
テーブルの変更  
始める  
データベースの作成  
関数を作成する  
インデックスの作成  
手順の作成  
テーブルの作成  
データベースの削除  
ドロップ機能  
インデックスを削除  
ドロップ手順  
テーブルを削除  
テーブルのロックを解除  
マスターデータをロード  
ロックテーブル  
テーブル名の変更  
テーブルを切り捨てる  
AUTOCOMMIT=1 を設定します  
取引を開始  

以下もご興味があるかもしれません:
  • PHP で MySQL ネストトランザクションを実装するための 2 つのソリューション
  • MySQL ストアド プロシージャの例 (トランザクション、出力パラメータ、ネストされた呼び出しを含む)

<<:  Vueのv-onパラメータの問題についてお話しましょう

>>:  Eclipse/Tomcat でホットデプロイメントとホットスタートを実装する方法

推薦する

Nest.js 認証検証方法の例

目次0x0 はじめに0x1 RBAC 実装0x2 クレームベースの承認0x3 統合 CASL 0x4...

CSS で div にスクロールを追加し、スクロール バーを非表示にする

CSS は div にスクロールを追加し、スクロール バーを非表示にします。具体的なコードは次のとお...

Apache Webサーバーのインストールと設定方法

信頼性が高く、人気があり、簡単に構成できる Web サーバーである Apache で独自の Web ...

Dockerコンテナ相互接続の予備的な実践についての簡単な説明

1. Dockerコンテナ間の相互接続Docker は現在、軽量の仮想化ソリューションとなっています...

CSS3 テキストシャドウ text-shadow プロパティの詳細な説明

テキストシャドウ text-shadow プロパティの効果: 1. 右下隅の影、左下隅の影、左上隅の...

MySQL ストアド プロシージャ関連の権限変更の問題

MySQL データベースを使用すると、他のユーザーが定義したストアド プロシージャを他のユーザーが変...

MySQL マルチバージョン同時実行制御メカニズム (MVCC) ソースコードの詳細な説明

目次1. はじめに2. MVCC (マルチバージョン同時実行制御メカニズム) 2.1 繰り返し読み取...

2列の水平タイムラインを実装するためのVueサンプルコード

目次1.コンポーネントtimelineH.vueを実装する2. コンポーネントの呼び出しこの記事では...

Vue+nodeはオーディオ録音・再生機能を実現

結果: コードロジックを実装するのが主な部分であり、具体的なページ構造を一つ一つ紹介することはありま...

デザインスキルを向上させる良い方法

いわゆる才能(左脳と右脳)つまり、芸術的な才能があるかどうかは、人間の左脳と右脳の分業によって主に決...

MySQL 文字セットの変更に関する実践的なチュートリアル

序文: MySQL では、システムが多くの文字セットをサポートしており、異なる文字セット間にはわずか...

読み取り専用と無効の違い

要約すると: Readonly は入力 (テキスト/パスワード) とテキスト領域に対してのみ有効です...

Tomcatが親の委任メカニズムを破壊する方法についての簡単な説明

目次JVM クラスローダーTomcat クラスローダークラスを検索ロードクラスクラスをロードしようと...

JavaScript関数の詳細な説明これを指す問題

目次1.関数内のこの方向1. 通常の機能2. コンストラクター3. オブジェクトメソッド4. イベン...

deepin apt コマンドを使用して最新バージョンの docker をインストールする方法

ステップ1: Ubuntuソースを追加するルートに切り替える suルートソフトウェアソースファイルの...