2016-06-11 4 views
0

質問は、MySQLのInnoDBテーブルでの同時SELECTとUPDATEの行動についてです。スキャン中に、以前にスキャンした行を更新します。更新はバッチ処理され、別の接続を使用してバックグラウンドスレッドで実行されます。 が既に読み取られた行を更新することに注意することが重要です。MySQLのMVCC(InnoDBは)

3つの質問:

  1. SELECTがまだ進行中であるため、ウィルInnoDBは更新された行の以前のバージョンを保存しますか?
  2. SELECTヘルプにREAD-UNCOMMITTEDを使用しますか?
  3. InnoDBが変更された行の以前のバージョンをredo-logに保存するかどうかを確認する方法を教えてください。

答えて

1

問題を無視して、トラブルに取得することはできませんコードを書く:

BEGIN; 
SELECT id ... LIMIT 20; -- get list of _possible_ candidates for action 
COMMIT; 
** 
foreach $candidate 
    BEGIN; 
    SELECT ..., is_candidate WHERE id = $candidate FOR UPDATE; 
    if still a candidate 
     process it 
     UPDATE ...; 
    COMMIT; 

誰かが**で、たとえば、中にスリップした場合、チェックは、後の二重処理を防止します。さらに、第2のBEGIN..COMMITは誰もが滑るのを防ぎます。

FOR UPDATE "行をロックします。これは重要。

このように処理することの利点は、取引が速いであり、それによって他のすべてへの影響が最小限に抑えられることです。

+0

答えがわかりません。私の場合のSELECTステートメントは、潜在的に行の*ロット*(100,000以上)を返します。問題は、私が何とかMySQLに最初の1000行の処理を完了したことを伝えることができるかどうかと、更新されている間にこれらの行の古いバージョンを保持する必要がないかどうかです。 – nimrodm

+0

おそらく唯一の方法は、あなた自身を塊に分けることです。 –

+0

まあ、LIMIT/OFFSETを使うのは非常に効率が悪く、サーバフェッチカーソルを使うと、MySQLは一時テーブルを作成しなければなりません。おそらく、主キーによるパーティション分割が最も効果的です。ありがとう! – nimrodm