7

SELECT FOR UPDATE(またはLOCK IN SHARE MODEについて少し助けが必要です。

約400000レコードのテーブルがあり、各行で2つの異なる処理関数を実行する必要があります。

テーブル構造は適切に次のとおりです。

data (
    `id`,
    `mtime`,  -- When was data1 set last
    `data1`,
    `data2` DEFAULT NULL,
    `priority1`,
    `priority2`,
    PRIMARY KEY `id`,
    INDEX (`mtime`),
    FOREIGN KEY ON `data2`
)

関数は少し異なります:

  • 最初の関数-すべてのレコードでループで実行する必要があり(かなり高速)、;に基づいてレコードを選択する必要がありますpriority1。セットdata1mtime
  • 2番目の関数-各レコードで1回だけ実行する必要があり(かなり遅い)、;に基づいてレコードを選択する必要がありますpriority2。セットdata1mtime

同じ行を同時に変更するべきではありませんが、selectは両方で1つの行を返す可能性があり(priority1priority2が異なります)、その場合はトランザクションが待機しても問題ありません(これが当てはまると思います)ブロックする唯一のケースです)。

次のクエリに基づいてデータを選択しています。

-- For the first function - not processed first, then the oldest,
-- the same age goes based on priority
SELECT id FROM data ORDER BY mtime IS NULL DESC, mtime, priority1 LIMIT 250 FOR UPDATE;

-- For the second function - only processed not processed order by priority
SELECT if FROM data ORDER BY priority2 WHERE data2 IS NULL LIMIT 50 FOR UPDATE;

しかし、私が経験しているのは、毎回1つのクエリだけが返されるということです。

だから私の質問は

  • (同じテーブル内の)別々の行の束で2つの別々のトランザクションで2つの別々のロックを取得することは可能ですか?
  • 最初のクエリと2番目のクエリの間にこれほど多くの衝突がありますか(デバッグに問題があります。デバッグ方法のヒントをSELECT ... FROM (SELECT ...) WHERE ... IN (SELECT)いただければ幸いです)。
  • ORDER BY ... LIMIT ...問題を引き起こす可能性がありますか?
  • インデックスとキーは問題を引き起こす可能性がありますか?
4

2 に答える 2

4

さらに先に進む前に確認する重要な事項:

  • テーブルエンジンがInnoDBであることを確認してください。そうでない場合、トランザクションが発生しないため、「更新用」は行をロックしません。
  • 「更新用」機能を正しく使用していることを確認してください。更新するものを選択すると、そのトランザクションにロックされます。他のトランザクションは行を読み取ることができる場合がありますが、元のロックトランザクションによってロックが解放されるまで、他のトランザクションによって更新、更新、または削除するために選択することはできません。
  • 物事をきれいに保つために、「START TRANSACTION」を使用してトランザクションを明示的に開始し、「for update」を選択して実行し、返されるレコードに対して実行することをすべて実行し、「COMMIT」を明示的に実行して終了します。トランザクションを終了します。

順序と制限は、私が知る限り、発生している問題に影響を与えません。Selectによって返されるものはすべて、ロックされる行になります。

あなたの質問に答えるには:

  1. (同じテーブル内の)別々の行の束で2つの別々のトランザクションで2つの別々のロックを取得することは可能ですか?
    はい。ただし、同じ行にはありません。ロックは、一度に1つのトランザクションの行レベルにのみ存在できます。
  2. 最初のクエリと2番目のクエリの間に多くの衝突がありますか(デバッグに問題があります。SELECT... FROM(SELECT ...)WHERE ... IN(SELECT)をデバッグする方法に関するヒントをいただければ幸いです)?
    行ロックが計算されている期間が短い可能性があります。これにより、2番目のクエリが遅延しますが、これらのselect for updateを一度に何百も実行しない限り、重大な遅延や顕著な遅延は発生しません。
  3. ORDER BY ... LIMIT ...で問題が発生する可能性はありますか? 私の経験ではありません。通常のselectステートメントで常に機能するのと同じように機能するはずです。
  4. インデックスとキーは問題を引き起こす可能性がありますか?
    十分なパフォーマンスを確保するために、インデックスは常に存在する必要がありますが、ロックの取得で問題が発生することはありません。
于 2013-01-26T23:57:58.493 に答える
0

受け入れられた回答のすべてのポイントは、次の2つのポイントを除いて、問題ないようです。「 Selectによって返されるものはすべて、ロックされる行になります。」&「インデックスとキーは問題を引き起こす可能性がありますか?しかし、ロックの取得に関して問題を引き起こすことはありません。

代わりに、選択して返す行を決定する際にDBによって内部的に読み取られるすべての行がロックされます。たとえば、以下のクエリはテーブルのすべての行をロックしますが、少数の行のみを選択して返す場合があります。select * from table where non_primary_non_indexed_column =?更新の場合インデックスがないため、DBはテーブル全体を読み取って目的の行を検索し、テーブル全体をロックする必要があります。

1つの行のみをロックする場合は、where句で主キーまたはインデックス付き列を指定する必要があります。したがって、適切な行のみをロックする場合、インデックス付けは非常に重要になります。

これは良いリファレンスです-https://dev.mysql.com/doc/refman/5.7/en/innodb-locking-reads.html

于 2017-05-09T08:18:53.923 に答える