4

inndob テーブルで「select ... for update」クエリの絶え間ないストリームがあります。

主な条件は、「column1」が 100 未満のすべてのフィールドを選択することです。

バックグラウンドでは、'column1' が 100 未満の挿入が発生する可能性がありますが、これは問題ではありません。そのクエリが実行されている間、または結果配列がフェッチされている間に発生したために更新の最初の選択が失敗した場合、次のクエリはそれをキャッチします。遅すぎる'。

これらの「select for update」クエリが 10 個待機している場合、inndob フィールドのロックが原因で、それらのキューイングを自分で処理する必要がありますか、それともデータベースに整理させますか? これを処理する正しい方法は、自分でクエリをキューに入れることだと思いますか?

したがって、スクリプトが到達すると

$sql = "SELECT * FROM ... FOR UDPATE"

事前に、キュー配列を確認して (?)、キュー配列が空でない場合は、このスクリプト呼び出しを最後にキュー配列に入れてから、キューの番号 1 に達するまで数ミリ秒ごとにキュー配列を確認しますか?

私はここで正しい線に沿って考えていますか...後で戻ってくるのではなく、今これを正しく理解することが重要です

編集:応答の可能性を高めるために追加できるものはありますか:)

4

1 に答える 1

3

InnoDB がキューイングを処理する必要があります。関連する行をロックして進行中のトランザクションがある場合、2 番目のトランザクションが別の SELECT FOR UPDATE ステートメントで同じロックを取得しようとすると、その 2 番目のステートメントは最初のトランザクションがコミットされるまで待機します。

これを自分でテストできます:

  1. 2 つの bash シェル ウィンドウを開き、各ウィンドウで mysql クライアントを実行します。
  2. START TRANSACTION各ウィンドウで 実行します。
  3. 最初のウィンドウでa を発行しSELECT ... FOR UPDATEます。
  4. 次に、同じ行をオーバーラップする WHERE 句を使用して、2 番目のウィンドウで同じことを行います。
  5. 最初のウィンドウでSHOW ENGINE INNODB STATUS、トランザクションとそのロックを実行して観察します。出力には次のようなものが含まれているはずです。

    LIST OF TRANSACTIONS FOR EACH SESSION:
    ---TRANSACTION 3B17, ACTIVE 4 sec starting index read
    mysql tables in use 1, locked 1
    LOCK WAIT 2 lock struct(s), heap size 376, 1 row lock(s)
    MySQL thread id 2, OS thread handle 0x7ff27ae2d700, query id 28 192.168.56.1 root Sending data
    select * from foo where id < 100 for update
    ------- TRX HAS BEEN WAITING 4 SEC FOR THIS LOCK TO BE GRANTED:
    RECORD LOCKS space id 266 page no 3 n bits 72 index `PRIMARY` of table `test`.`foo` trx id 3B17 lock_mode X waiting
    ------------------
    TABLE LOCK table `test`.`foo` trx id 3B17 lock mode IX
    RECORD LOCKS space id 266 page no 3 n bits 72 index `PRIMARY` of table `test`.`foo` trx id 3B17 lock_mode X waiting
    ---TRANSACTION 3B16, ACTIVE 70 sec
    2 lock struct(s), heap size 376, 2 row lock(s)
    MySQL thread id 1, OS thread handle 0x7ff27ae6e700, query id 29 192.168.56.1 root
    show engine innodb status
    TABLE LOCK table `test`.`foo` trx id 3B16 lock mode IX
    RECORD LOCKS space id 266 page no 3 n bits 72 index `PRIMARY` of table `test`.`foo` trx id 3B16 lock_mode X
    

上記で、トランザクション 3B16 がロックを保持しており、トランザクション 3B17 がロックを待機していることに注意してください。

トランザクション 3B16 は、現在「show engine innodb status」を実行していることを示していますが、以前の SELECT ... FOR UPDATE で取得したロックを保持しています。そのステートメントが終了しても、トランザクションは終了せず、トランザクションが終了するとロックが解放されます。

トランザクション 3B17 が数lock_wait_timeout秒以上待機し、最初のトランザクションがまだコミットまたはロールバックされていない場合、待機中のステートメントは放棄され、次のエラーが発生します。

ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
于 2013-05-14T23:09:00.810 に答える