1. ホーム
  2. mysql

[解決済み] MySQLのFOR UPDATEロックを使用する場合、何が正確にロックされるのでしょうか?

2022-11-05 18:41:59

質問

これは完全な/正しい MySQL クエリではなく、擬似的なコードです。

Select *
 from Notifications as n
 where n.date > (CurrentDate-10 days)
 limit by 1
 FOR UPDATE

http://dev.mysql.com/doc/refman/5.0/en/select.html の状態になります。 ページまたは行ロックを使用するストレージ エンジンで FOR UPDATE を使用する場合、クエリによって検査される行は現在のトランザクションが終了するまで書き込みロックされます。

ここで MySQL によってロックされているのは返された 1 つのレコードだけですか、それとも 1 つのレコードを見つけるためにスキャンしなければならないすべてのレコードですか?

どのように解決するのですか?

試してみませんか?

データベースをセットアップする

CREATE DATABASE so1;
USE so1;
CREATE TABLE notification (`id` BIGINT(20), `date` DATE, `text` TEXT) ENGINE=InnoDB;
INSERT INTO notification(id, `date`, `text`) values (1, '2011-05-01', 'Notification 1');
INSERT INTO notification(id, `date`, `text`) values (2, '2011-05-02', 'Notification 2');
INSERT INTO notification(id, `date`, `text`) values (3, '2011-05-03', 'Notification 3');
INSERT INTO notification(id, `date`, `text`) values (4, '2011-05-04', 'Notification 4');
INSERT INTO notification(id, `date`, `text`) values (5, '2011-05-05', 'Notification 5');

ここで、2つのデータベース接続を開始します

接続1

BEGIN;
SELECT * FROM notification WHERE `date` >= '2011-05-03' FOR UPDATE;

コネクション2

BEGIN;

MySQL がすべての行をロックする場合、次のステートメントはブロックされます。返された行だけをロックするのであれば、ブロックされることはないはずです。

SELECT * FROM notification WHERE `date` = '2011-05-02' FOR UPDATE;

そして実際にブロックされます。

興味深いことに、読み込まれるようなレコードを追加することもできません、つまり

INSERT INTO notification(id, `date`, `text`) values (6, '2011-05-06', 'Notification 6');

のブロックもあります。

この時点では、MySQL が特定の割合の行がロックされたときにテーブル全体をロックするのか、それとも実際に SELECT ... FOR UPDATE クエリの結果が他のトランザクションによって決して変更されないようにするために、実際に本当にインテリジェントなのかどうか、この時点ではわかりません。 INSERT , UPDATE または DELETE のように)ロックが保持されている間