sql >> データベース >  >> RDS >> Mysql

Mysqlでの行レベルのロック

    FOR UPDATEの代わりに LOCK IN SHARE MODEを使用します 。 FOR UPDATE 他のトランザクションが行を読み取るのを防ぎます。 LOCK IN SHARE MODE 読み取りは許可しますが、更新はできません。

    参照:MySQLマニュアル

    ------セッション1

    START TRANSACTION;
    SELECT * FROM test WHERE t=1 LOCK IN SHARE MODE;
    UPDATE test SET NAME='irfandd' WHERE t=2;
    COMMIT;
    

    -----セッション2(もうブロックされていません:))

    START TRANSACTION;
    UPDATE test SET NAME='irfandd' WHERE t=4;
    COMMIT;
    

    更新:

    テーブルにインデックスがないことに気付く tに 、次の説明があります:

    まず、トランザクションT1が行1をロックします SELECT * FROM test WHERE t=1 FOR UPDATE

    次に、トランザクションT2はUPDATE test SET NAME='irfandd' WHERE t=4を実行しようとします。 。影響を受ける行を見つけるには、行1を含むすべての行をスキャンする必要があります。 。ただし、これはロックされているため、T2はT1が終了するまで待機する必要があります。何らかの種類のインデックスがある場合は、WHERE t=4 インデックスを使用して、行1かどうかを判断できます t=4が含まれています かどうかにかかわらず、待つ必要はありません。

    オプション1: test.tにインデックスを追加します 更新で使用できるようになります。

    オプション2: LOCK IN SHARE MODEを使用します 、これは読み取りロックのみを設定することを目的としています。残念ながら、このオプションはデッドロックを作成します。興味深いことに、T2トランザクションは実行され(行4を更新)、T1は失敗します(行2を更新)。 T1は行4を読み取りロックしているようです また、T2がそれを変更するため、トランザクション分離レベルが原因でT1が失敗します(デフォルトでREPEATABLEREAD )。最終的な解決策は、トランザクション分離レベル<で遊ぶことです。 / a> 、READ UNCOMMITTEDを使用 またはREAD COMMITTED トランザクションレベル。

    最も単純なのはオプション1 、私見ですが、それはあなたの可能性次第です。



    1. 2つのテーブルの結合でクエリを更新する

    2. JSONタイプ内の配列要素のクエリ

    3. MySQLで最も一致する行を見つける(InnoDB)

    4. MySQLでCOUNTを使用するときにnullではなく0を返す方法