MySqlのドキュメントに従って、MySqlは複数の粒度のロック(MGL)をサポートしています。
開いたターミナル-1:
// mysqlに接続されています
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>
開いたままにし、ターミナル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
取得する行はたくさんありますが、T2はt1が完了するまで待機します。
ターミナル1をそのまま残します。ターミナル2に移動します。
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で、T2はT1がロックしたのと同じ行のセットを待つのですか?
これは、制限のない選択クエリ(limintパラメーターを使用した場合でも、別の範囲でも試した)がテーブル全体をブロックすることを意味しますか?
端末とトランザクションを開きました:
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;
T1をコミット(またはロールバック)するまで、T2は成功しませんでした。
これらのロックの仕組みを説明します。
1ケース
T1がテストテーブルの一部の行を更新しようとしています。このトランザクションは、すべてのテーブルにIXロックを配置し、最初の5行にXロックを配置します。
T2がテストテーブルの一部の行を更新しようとしています。このトランザクションは、すべてのテーブルにIX(IXはIXと互換性があるため)ロックをかけ、最初の5行を試みますが、XはXと互換性がないため実行できません。
だから私たちは元気です。
2.1ケース
T1がテストテーブルの一部の行を更新しようとしています。このトランザクションは、すべてのテーブルにIXロックを配置し、最初の5行にXロックを配置します。
T2は、テストテーブルからいくつかの行を選択しようとしています。そして、それはロックを配置しません(InnoDBが非ロック読み取りを提供するため)
2.1ケース
T1がテストテーブルの一部の行を更新しようとしています。このトランザクションは、すべてのテーブルにIXロックを配置し、最初の5行にXロックを配置します。
T2は、テストテーブルの一部の行を更新(更新用に選択)しようとしています。テーブル全体にISを配置し、行にSロックを取得しようとしますが、XとSに互換性がないため失敗します。
また、常に分離レベルに注意してください。レベルが異なると、ロックを解放/獲得するメカニズムが異なります。
それが役に立てば幸い