2016-05-20 40 views
1

現在取引中であるかどうかをMySQLに知らせる方法はありますか?私はコマンドラインmysqlクライアントからのインタラクティブセッション中に、いくつかのトランザクションを開いたり閉じたりしていますが、今はトランザクション中ではないはずですが、おそらく私のように動作しています。どうすれば接続状態を調べたり確認したりできますか?私は自分の運を試してSHOW TRANSACTIONとタイプしましたが、そのようなことはありません。mysqlで現在アクティブなトランザクションを表示

デューデリジェンス:

私は(もちろん、およびtransaction documentation)他の質問を見てきました、と答えを見つけることができませんでした。 This questionは、接続が切断された後のトランザクションのリカバリに関するものです。 This oneは、他のスレッドでアクティブなトランザクションがあるかどうかを確認しているようです。 私の接続がトランザクション中であるかどうかを確認したい。

また、hereとしてSELECT @@AUTOCOMMIT FROM DUALを試しました。しかし、それは助けにはなりません:私はトランザクションを開始すると、その値は変更されずに残ります1( "自動コミットが有効")。

答えて

1

information_schemainnodb_trxは、InnoDB内の取引にいるかどうかをお知らせします。このキャッチは、テーブルにまだアクセスしていないか、または明示的に読み込みスナップショットを作成していないと、のMySQL(「サーバーレイヤー」)内にあり、InnoDB(「ストレージエンジンレイヤー」) )。

mysql> SELECT count(1) FROM information_schema.innodb_trx 
    -> WHERE trx_mysql_thread_id = CONNECTION_ID(); 
+----------+ 
| count(1) | 
+----------+ 
|  0 | 
+----------+ 
1 row in set (0.00 sec) 

mysql> START TRANSACTION; 
Query OK, 0 rows affected (0.00 sec) 

さて、私は前にしませんでしたが、は今私は...

mysql> SELECT count(1) FROM information_schema.innodb_trx 
    -> WHERE trx_mysql_thread_id = CONNECTION_ID(); 
+----------+ 
| count(1) | 
+----------+ 
|  0 | 
+----------+ 
1 row in set (0.00 sec) 

トランザクションを持っている、と...まだinnodb_trxで私の現在のCONNECTION_ID()は何もありません。

しかし、私はへの書き込みまたはちょうどのInnoDBテーブルから読み込まれた場合...

mysql> SELECT COUNT(1) FROM t1; 
+----------+ 
| COUNT(1) | 
+----------+ 
|  301 | 
+----------+ 
1 row in set (0.00 sec) 

... InnoDBはそれを認識しているので、今、私は、私のトランザクションを見ることができます。

mysql> SELECT count(1) FROM information_schema.innodb_trx 
    -> WHERE trx_mysql_thread_id = CONNECTION_ID(); 
+----------+ 
| count(1) | 
+----------+ 
|  1 | 
+----------+ 
1 row in set (0.00 sec) 

mysql> ROLLBACK; 
Query OK, 0 rows affected (0.00 sec) 

、私のMVCCビューが始動するストレージエンジンを教えていない、後でサーバーを教えて、今

mysql> SELECT count(1) FROM information_schema.innodb_trx 
    -> WHERE trx_mysql_thread_id = CONNECTION_ID(); 
+----------+ 
| count(1) | 
+----------+ 
|  0 | 
+----------+ 
1 row in set (0.00 sec) 

...のは、それがなくなっていることを確認してみましょう:

mysql> START TRANSACTION WITH CONSISTENT SNAPSHOT; 
Query OK, 0 rows affected (0.00 sec) 

注意を私の孤立したレベルで許可されていない限り、これは実際に私に "一貫性のある"スナップショットを与えません。しかし、InnoDBは私がここにいることを知っているだけで十分です。

mysql> SELECT count(1) FROM information_schema.innodb_trx 
    -> WHERE trx_mysql_thread_id = CONNECTION_ID(); 
+----------+ 
| count(1) | 
+----------+ 
|  1 | 
+----------+ 
1 row in set (0.00 sec) 

...そしてInnoDBはトランザクションをすぐに知ります。


今、あなたが現在取引中であるかどうかを判断する別の方法があります。または、より正確に言えば、私は今あなたがではないと判断する別の方法があると言うべきです。

これは、トランザクション内で実行する必要があるストアドプロシージャの場合に使用します。呼び出し元は、開始およびコミットまたはロールバックを担当し、アクティブなトランザクションがない場合はプロシージャが実行を拒否します。どうやって?

プロシージャは、トランザクションを持っていればサイレントに成功する別のプロシージャを呼び出しますが、そうでなければ例外をスローします。 1つのプロシージャが2番目のプロシージャをコールし、2番目のプロシージャが例外をスローすると、最初のプロシージャでエラーをキャッチするためにHANDLERがインストールされていない限り、同じ例外が発生して終了します。

私の外側のプロシージャは、このプロシージャを呼び出すときに、アクティブなトランザクションがありますならば、何も起こらない、と外側のプロシージャの実行を許可されています

mysql> START TRANSACTION; 
Query OK, 0 rows affected (0.00 sec) 

mysql> CALL mysql.require_transaction; 
Query OK, 0 rows affected (0.00 sec) 

^^^この^^^は私が近くに何をすべきかですトランザクション内から呼び出された場合にのみ実行する必要のあるストアドプロシージャ内の最初の部分です。

エラーはありませんでした。トランザクションに参加しました。これがそれを呼び出す別の手続きだったならば、その手続きは単に次の命令に続きます。

しかし、私たちは、私のrequire_transactionプロシージャを呼び出して、我々はトランザクションに含まれていない場合:

mysql> ROLLBACK; 
Query OK, 0 rows affected (0.00 sec) 

mysql> CALL mysql.require_transaction; 
ERROR 1644 (42000): you must have an active database transaction before attempting 
this operation 

ニート。カスタムエラーメッセージで呼び出し元をクラッシュさせます。どうやって?

DELIMITER $$ 
CREATE PROCEDURE `mysql`.`require_transaction`() 
BEGIN 

-- test the session's transactional status, 
-- throwing an exception if we aren't in a transaction, 
-- but finishing successfully if we are 

DECLARE CONTINUE HANDLER 
     FOR 1305 
     SIGNAL SQLSTATE '42000' 
     SET MESSAGE_TEXT = 'you must have an active database transaction before attempting this operation'; 

SAVEPOINT `we created to be sure you were in a transaction`; 
ROLLBACK TO SAVEPOINT `we created to be sure you were in a transaction`; 

END $$ 
DELIMITER ; 

これは、私は、MySQLの設計における重要な監督であると信じるもののための私の長年の回避策されている - あなたが取引に現在あるかどうか、SQLインターフェースから、決定的に決定する明白なことができません。これが機能する理由はここにあります:

  • SAVEPOINTを作成し、すぐにそれに戻って転がり、本質的に何もしません。同じ名前のアクティブなセーブポイントがない限り、害はなく、ファウルはありません。私はSAVEPOINTのために非常に起こりそうな名前we created to be sure you were in a transactionを使用しました。

  • SAVEPOINTを作成することは、トランザクションに参加していない場合は実行できませんが、実際は黙って失敗します。

  • 存在しないSAVEPOINTにロールバックするとエラー1305がスローされるため、トランザクションに参加していない場合は作成されていないため、存在しないため、エラーが発生します。トランザクション中の場合は、SAVEPOINTが作成されてから解放され、トランザクションはそのままになります。

mysql> ROLLBACK TO SAVEPOINT `we created to be sure you were in a transaction`; 
ERROR 1305 (42000): SAVEPOINT we created to be sure you were in a transaction does not exist 
mysql> 

気の利いたハックだアハハハ。これで、私が私の偽のセーブポイントの名前を使用した理由がわかります。オブジェクト名に「存在しません」というエラーメッセージが追加されます。SIGNALを持っていないのMySQL 5.1、オン

、私のrequire_transactionストアドプロシージャは、単にほとんど意味のある...または誰かが(私を)DBAを聞いて来ることを十分に少なくとも意味のある、その本来のエラーで終了しますその意味。

MySQL Server 5.5以降では、エラー1305をCONTINUE HANDLERでキャッチし、SIGNALを使用して独自のカスタムエラーメッセージを設定することができます。

セーブポイントを設定してすぐにロールバックするのは、あなたがトランザクション中であるかどうかを判断するうえで、悲劇的だが確かな方法です。

+1

ありがとう! SQLは、対話型の使用や人為的なエラー(ほぼ同じこと)に対応していないだけです。私のユースケースはインタラクティブなコンソールなので、「SAVEPOINTを作成してそれにロールバックしてみてください」というのは、私のニーズにとっては非常に良い解決策です。 (たぶんあなたはTLの一番上にそれを加えるべきでしょう:DNRのイントロ:-) – alexis

+0

私はその提案を勧告のもとで受け取り、答えのリファクタリングを少し考えます。ありがとう。 :) –

1

22.31.4 The INFORMATION_SCHEMA INNODB_TRX Tableをお試しください。

SELECT 
    COUNT(`trx_id`) `inTransaction?` 
FROM 
    `INFORMATION_SCHEMA`.`INNODB_TRX` 
WHERE 
    `trx_mysql_thread_id` = CONNECTION_ID(); 
+0

私はちょうどやった、私は取引を開始する前後に私に '0'を与えている。 – alexis

+0

また注目に値する:それは 'PROCESS'特権を必要とするので、(それを修正することができても)必ずしもオプションではない。 – alexis

+0

それはうまくいくように見えます。奇妙な。私は 'innodb_trx'テーブルをチェックし、' START TRANSACTION'を呼び出した後は完全に空のままです。 (私はデータベースに何も変更を加えませんでした。) – alexis

関連する問題