2012-01-13 4 views
25

は、MySQLは複数の粒度ロック(MGL)をサポートしています。MySQLの「更新のために選択行動のMySQLのドキュメントを1として

場合-1

オープン端子1:

//

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

mysql> select id, status from tracking_number limit 5 for update; 
+----+--------+ 
| id | status | 
+----+--------+ 
| 1 |  0 | 
| 2 |  0 | 
| 3 |  0 | 
| 4 |  0 | 
| 5 |  0 | 
+----+--------+ 
5 rows in set (0.00 sec) 
mysql> 

をMySQLへの接続は、端子2を開いて開放左:

// MySQLへの接続

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

mysql> select id, status from tracking_number limit 5 for update; 

<!-- Hangs here. and after some time it says--> 
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction 

取得する行の多くがありますがt1が完了するまで、T2は待機します。

ケース2

端末2にis.Nowように端子1を左:

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

<!-- case 2.1 --> 
mysql> select id, status from tracking_number where id=1; 
+----+--------+ 
| id | status | 
+----+--------+ 
| 1 |  0 | 
+----+--------+ 
1 row in set (0.00 sec) 

mysql> select id, status from tracking_number where id=2; 
+----+--------+ 
| id | status | 
+----+--------+ 
| 2 |  0 | 
+----+--------+ 
1 row in set (0.00 sec) 

<!-- case 2.2 --> 
mysql> select * from tracking_number where id=2 for update; 
<!-- Hangs here. and after some time --> 
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction 
  1. しかし、ケース1内に、T2は、T1の行の同じセットを待つ理由ロックされていますか?

  2. 無制限の選択クエリ(limintパラメータであっても、私は異なる範囲で試してみました)がテーブル全体をブロックしていることを意味しますか?

  3. フィールドを指定しないでトランザクションを個別にロックする方法はありますか(フィールド=値を使用しないで)。
  4. 一般的に(またはJava並行ロックごとに)、書き込みロックは排他的であり、読み取りは無効です。レコードは書き込みロックモードになっているものの場合2.1で、T2は同じレコードを読み取ることができますか?これはロックされている点は何ですか?
  5. ケース2.2は理解されています。

は、端末と取引を開設:

mysql> update tracking_number set status=4 where status=0 limit 5; 
Query OK, 5 rows affected (0.00 sec) 
Rows matched: 5 Changed: 5 Warnings: 0 

そこを去り、別の端末とのトランザクションを開いた:

mysql> update tracking_number set status=5 where status=0 limit 5; 

T2は、私がコミットされるまで成功(またはロールバック)T1ませんでした。

  1. この現象はなぜですか?

答えて

22

私はあなたの例を通過し、これらのロックがどのように機能するかを説明しましょう:

T1は、テストテーブル内の一部の行を更新したい

1ケース。このトランザクションは、すべてのテーブルにIXロックを入れ、最初の5行にXロックを入れます。

T2はテストテーブルの一部の行を更新します。このトランザクションは、IXを置く(IX IXと互換性があるため)、すべてのテーブルをロックオンし、最初の5行にしようとしますが、Xが

だから我々は細かいX

と互換性がありませんので、それはそれを行うことはできません。

2.1ケース

T1は、テストテーブル内の一部の行を更新したいと考えています。このトランザクションは、すべてのテーブルにIXロックをかけ、最初の5行にXロックを入れます。

T2はテストテーブルからいくつかの行を選択します。 (InnoDBは非ロックを提供して読み取るため)そしてそれは

T1は、テストテーブル内の一部の行を更新したい

2.1ケースロックをかけません。このトランザクションは、すべてのテーブルにIXロックをかけ、最初の5行にXロックを入れます。

T2は、テストテーブルから一部の行を更新(更新を選択)したいとします。テーブル全体にISを配置し、行にSロックを取得しようとします.XとSは互換性がないため失敗します。


また、常に分離レベルに注意してください。異なるレベルの原因異なるメカニズム解放するために/取得のロック

それは

+0

ありがとう@ravnurに役立ちます願っています。レコードのフィールドを指定せずに(つまり、フィールド=値を使用せずに)トランザクションを独立してロックできるようにする方法はありますか? –

+1

=独立して=同時に? 「はい」の場合は、分離レベルを「DIRTY READS」に設定すること以外は実行できません(このオプションを試してください)。あなたの答えが "いいえ"であれば、 'LOCK TABLE'を試してみるか、分離レベルを" SERIALIZABLE "として設定してください(しかし、あなたの答えは"はい "であるはずです)。 – ravnur

+0

私の答えは「はい」です。あなたの明確化のためにありがとう。答えは –

関連する問題