web-dev-qa-db-ja.com

selectステートメントをブロックするにはどうすればよいですか?

こんにちは私は学習のために、SQL selectステートメントを別の単純なSQL削除または更新ステートメントによって意図的にブロックさせようとしています。私はInnoDBテーブルのみを好みます。

テストを準備するために、テーブルを作成しました

CREATE TABLE `test`.`client` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB;

1,000,000行をテーブルに挿入しました。


それでは、テストを開始します。

MySQLクライアント#1では、すべての行を削除しました。

mysql #1> delete from client;

削除がまだ実行されている間に、別のMySQLクライアント#2で、行を選択しようとします。

mysql #2> select * from client where id=1;
+---------+------+
| id      | name |
+---------+------+
| 1       | joe  |
+---------+------+
1 row in set (0.00 sec)

結果は即座に表示され、選択はブロックされませんでした。


次に、別のテストを試します。 1,000,000行をテーブルに挿入します。

MySQLクライアント#1で、すべての行を更新します。

mysql #1> update client set name='Bill';

更新がまだ実行されている間に、別のMySQLクライアント#2で、行を選択しようとします。

mysql #2> select * from client where id=100;
+-----+------+
| id  | name |
+-----+------+
| 100 | joe  |
+-----+------+
1 row in set (0.00 sec)

mysql #2> select * from client where id=1000;
+------+------+
| id   | name |
+------+------+
| 1000 | joe  |
+------+------+
1 row in set (0.00 sec)

結果は即座に表示され、選択はブロックされませんでした。

さて、私の質問ですが、InnoDBテーブルを使用して、SQL selectステートメントが別の単純なSQL削除または更新ステートメントによってブロックされることをどのように示すことができますか?それともMySQLにはブロッキングの問題はありませんか?

PS私は、2つのプロセスが互いにデッドロックするのではなく、1つの大きな更新または挿入による選択のブロックをシミュレートしようとはしていません。

4
davidjhp

SELECTによるデッドロックは、さまざまな方法で実行できます。それらについての投稿を書いた

このレベルはREPEATABLE READに似ていますが、自動コミットが無効になっている場合、InnoDBはすべてのプレーンSELECTステートメントを暗黙的にSELECT ... LOCK IN SHARE MODEに変換します。自動コミットが有効な場合、SELECTは独自のトランザクションです。したがって、読み取り専用であることが知られており、一貫した(非ロック)読み取りとして実行され、他のトランザクションをブロックする必要がない場合は、シリアル化できます。 (他のトランザクションが選択された行を変更した場合にプレーンSELECTを強制的にブロックするには、自動コミットを無効にします。)

すぐに追いかけて、あなたはただ使うことができます

  • SELECT ... FOR UPDATE、次にそれらの行に対してSELECTを試してください
  • SELECT ... LOCK IN SHARE MODE、次にそれらの行をUPDATEまたはDELETEしてみます
  • MySQLドキュメントを参照

試してみる !!!

2
RolandoMySQLDBA

セッション2でその行をまったく表示しないことはできますか?つまり、セッション1が更新されているときに、セッション2が選択で同様にアクセスしない可能性がありますか?

0
anisakras