0

データベースで特定のクエリを実行すると、かなり頻繁に次のエラーが発生します (すべてのテーブルは InnoDB ストレージ エンジンを使用します)。

クエリはDELETE FROM sessions WHERE userid != 0 AND lastactivity < 1289594761 AND admin = 1 AND userid NOT IN (SELECT userid FROM users WHERE (userflags & 1048576))

NOT IN 部分を WHERE ステートメントに追加したときに、エラーが発生し始めました。これが原因で問題が発生するのはなぜですか? また、これを防ぐにはどうすればよいですか?

4

2 に答える 2

2

簡単な解決策は、これを 2 つの連続するクエリに分割することです。すなわち、:

SELECT userid を #tmptable FROM users WHERE (userflags & 1048576) に入力します。

DELETE FROM sessions WHERE userid != 0 AND lastactivity < 1289594761 AND admin = 1 AND userid NOT IN (#tmptable からユーザー ID を選択);

そうすれば、2 番目のテーブルの値のローカル セッション コピーを使用して、読み取りロックを発生させません。ただし、これは簡単な解決策にすぎません。定期的に再利用する場合は、これら 2 つのテーブルにアクセスするすべてのアクティビティのトランザクション ロック設定を分析し、クエリを書き直すことをお勧めします。

于 2010-11-12T21:14:03.313 に答える
2

おそらく、これははるかに遅いクエリであるため、エラーがより頻繁に発生するでしょう。

&op onuserflagsは、サブクエリをインデックス付けできなくします。フラグ ワードは、インデックス作成を無効にする計算を必要とするため、通常は適切なスキーマ設計ではありません。クエリのビット テストを頻繁に行っている場合は、小さなデータ型 (例: TINYINT) の個別の列を使用する方がよい場合があります。

スキーマが見た目どおりに機能する場合は、単純な JOIN を使用してこれを実行できるはずです。これは通常、サブクエリよりも優れたパフォーマンスを発揮します。

DELETE sessions
FROM sessions
JOIN users ON users.userid=sessions.userid
WHERE sessions.lastactivity<1289594761 AND admin=1
AND (users.userflags&1048576)=0

(joins onDELETEは、MySQL の非 ANSI SQL 拡張機能です。)

于 2010-11-12T21:27:32.933 に答える