MySQLの排他ロック

stavros.zavrakas:

私たちは、下記の表を持っています:

mysql> desc journeys ;
+---------------+------------+------+-----+---------+-------+
| Field         | Type       | Null | Key | Default | Extra |
+---------------+------------+------+-----+---------+-------+
| journey_id    | char(36)   | NO   | PRI | NULL    |       |
| is_completed  | tinyint(1) | NO   |     | 0       |       |
| user_id       | char(36)   | NO   |     | NULL    |       |
| created_at    | datetime   | NO   |     | NULL    |       |
| updated_at    | datetime   | NO   |     | NULL    |       |
| pack_id       | char(36)   | YES  | MUL | NULL    |       |
| family_id     | char(36)   | YES  | MUL | NULL    |       |
+---------------+------------+------+-----+---------+-------+

mysql> desc packs ;
+---------------+------------+------+-----+---------+-------+
| Field         | Type       | Null | Key | Default | Extra |
+---------------+------------+------+-----+---------+-------+
| pack_id       | char(36)   | NO   | PRI | NULL    |       |
| is_published  | tinyint(1) | NO   |     | 0       |       |
| order         | int(11)    | NO   |     | NULL    |       |
| created_at    | datetime   | NO   |     | NULL    |       |
| updated_at    | datetime   | NO   |     | NULL    |       |
| family_id     | char(36)   | NO   | MUL | NULL    |       |
+---------------+------------+------+-----+---------+-------+

分離レベルはREPEATABLE_READあります。

ここでの用語集によると:https://dev.mysql.com/doc/refman/8.0/en/glossary.html#glos_exclusive_lock

排他的ロックは、任意防止するロックの一種であり、同じ行をロックから他のトランザクショントランザクション分離レベルに応じて、ロックのこの種は、同一の行に書き込む他のトランザクションをブロックするか、または、同じ行を読んでから、他のトランザクションをブロックするかもしれません。

私たちは以下のようなルックスを持っているという論理は、(user_id異なる値をとります):

START TRANSACTION;
SELECT * FROM journeys WHERE user_id = <user_id> FOR UPDATE ;
# COMMIT;

以下は、テストのビットがあります。私は1つのターミナルウィンドウ(端末#1)を開いて、私は以下のステートメントを実行します。

START TRANSACTION;
SELECT * FROM journeys WHERE user_id = user_id_1 FOR UPDATE ;

私は第二の端子(端子#2)ウィンドウを開き、Iは、以下のステートメントを実行します。

START TRANSACTION;
SELECT * FROM journeys WHERE user_id = user_id_2 FOR UPDATE ;

今、端末#2停止我々は、端末#1上のトランザクションをコミットしたことがないので。

私の仮定は、第1端子#1の条件は、端末#2内のステートメントが異なるため、2番目の端末がコミットする最初のを待たないだろうということでした。私は排他ロックが同じ行をロックし、他の取引を防止することを言う排他ロックの定義に私の仮定を基づかよ。これは間違った仮定ですか?はいがどのように行をロックするために実現することができれば、我々は最初の状態に持っていますか?

私が条件で、主キーを使用する場合、それは違うようです。端末#2以下の場合はコミットする端末#1を待っていません。

terminal #1
START TRANSACTION;
SELECT * FROM journeys WHERE journey_id = journey_id_1 FOR UPDATE ;

端末#でステートメント2

terminal #2
START TRANSACTION;
SELECT * FROM journeys WHERE journey_id = journey_id_2 FOR UPDATE ;

私たちは主キーが含まれていない条件を持っていると何が正確に排他的ロックとどうなりますか?私たちは、テーブル全体をロックしていますか?

ビルKarwin:

あなたのようなインデックスのない列に条件を持っている場合はい、あなたは、テーブル内のすべての行をロックしていますuser_id

ロックは、すべての「検討」の行に適用されます。あなたの条件は、WHERE user_id = <user_id>調べる必要があり、すべてのテーブルの行を、彼らはの値と一致するかどうかを確認するために一つずつをテストします<user_id>

両方のクエリは、彼らが別の特定の値を探しているにもかかわらず、行のセット全体を検討している<user_id>ので、彼らの紛争、。

あなたは上のインデックスがあった場合user_id、カラムを、その後、MySQLは最初に一致する行を検索し、そのインデックスを使用することになり、その後、唯一の一致する行を調べ行になるので、ロックされます。

これは、トランザクション分離レベルとは何の関係もありません。ロックのこれらのタイプは、すべてのトランザクション分離レベルで発生します。

おすすめ

転載: http://43.154.161.224:23101/article/api/json?id=372729&siteId=1