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 でホットデプロイメントとホットスタートを実装する方法

推薦する

Mybatis マッパー動的プロキシの原理の分析

序文動的プロキシの原理を説明する前に、まず、mybatis を統合した後の dao 層の 2 つの実...

Easyswoole ワンクリック インストール スクリプトとパゴダ インストール エラー

よくある質問easyswoole を初めて使用する場合は、次のような問題に遭遇することがよくあります...

Linux で MySQL のデフォルト エンコーディングを変更する方法

開発プロセス中に、MySQL データベースを復元した後にデータベース データに文字化けが発生した場合...

ubuntu20.04 LTSにdockerをインストールする方法

ゼロ: 古いバージョンをアンインストールするDocker の古いバージョンは、docker、dock...

MySQLが大量のデータを処理する際にクエリ速度を最適化するいくつかの方法

実際に参加したプロジェクトでは、MySQL テーブルのデータ量が数百万に達すると、通常の SQL ク...

HTML ページ ソース コード レイアウトの概要_Powernode Java Academy

HTML ページ ソース コード レイアウトの概要この紹介では、Google のホームページのソー...

HTML 基本構造_Powernode Java アカデミー

多くの場合、Web ページ開発を学ぶときに最初に印象に残るのは、html または htm サフィック...

Linux でのマルチスレッドおよびマルチプロセス クラッシュのシミュレーションに関する簡単な説明

結論:マルチスレッド環境では、スレッドの 1 つがクラッシュすると、他のスレッド (プロセス全体) ...

axiosリクエストをvueでカプセル化する方法

実際、Vueでaxiosをカプセル化するのは非常に簡単ですまず、srcパスにhttpフォルダを作成し...

Vueデータプロキシの詳細な説明

目次1. これからお話しするのは、フロントエンド担当者がvue-cliで完了できるソリューション、デ...

太陽系の惑星のアニメーション効果を実現するHTML+CSS3コード

太陽系の 8 つの惑星(衛星を除く)のアニメーションを作成します。すべての惑星は太陽の周りを回ってい...

MySQL5.7 マスタースレーブ構成例の分析

MySQL5.7マスタースレーブ構成の実装方法、具体的な内容は次のとおりですインストール環境:マスタ...

MySQL データベースのエンコーディングを utf8mb4 に変更する方法

utf8mb4 エンコーディングは utf8 エンコーディングのスーパーセットであり、utf8 と互...

Vue+swiperでタイムライン効果を実現

この記事では、タイムライン効果を実現するためのvue+swiperの具体的なコードを参考までに共有し...

CentOS 7 はネットワークカードを変更した後、インターネットにアクセスできません

不明なドメイン名 www.baidu.com を Ping するホストのIPアドレスを変更する右クリ...