2009-06-01 25 views
1
DB Table: 
id  int(6) 
message char(5) 

DBテーブルにレコード(メッセージ)を追加する必要があります。メッセージが重複している場合(このメッセージは既に別のIDで存在しています)、両方のメッセージを削除(または何らかの方法で無効化)してIDの応答を取得します。パフォーマンスの挿入/削除

1つのクエリでのみ実行できますか?パフォーマンスのヒント?

P.S. 私はPostgreSQLを使用しています。

私が心配主な私の問題は、...

多くのおかげで二つ以上のクエリでこれを実行するときにロックを使用する必要があります!

+0

どのRDBMS? .... –

答えて

2

本当にロックを心配したい場合は、これを実行します。

  1. UPDATEテーブルSETステータス= 'INACTIVE' WHERE id = 'key';

    これが成功した場合は、重複があります。

  2. 追加の非アクティブレコードを挿入します。あなたの複製物で何でもしてください。
  3. これが失敗した場合、重複はありません。

    • 新しいアクティブレコードを挿入します。
  4. コミット。

これはすぐに排他的ロックを獲得します。代替案はそれほど素晴らしいものではありません。

  • INSERTで開始し、重複を確認しても、更新を開始するまでロックがかかりません。これが問題なのかどうかは明らかではありません。

  • SELECTで始めると、LOCK TABLEを追加する必要があります.LOCK TABLEを使用すると、選択された行が更新されるように保持されます。行が見つからない場合、挿入は正常に動作します。

  • 同時に複数のライターがあり、同時に2人のライターが同時にアクセスしようとすると、行レベルのロックを許容できない場合があります。

    これを考慮してください。

    1. プロセスAはLOCK ROWとSELECTを実行しますが、行は検出されません。

    2. プロセスBはLOCK ROWとSELECTを実行しますが、行は検出されません。

    3. プロセスAは、INSERTとCOMMITを行います。

    4. プロセスBは、INSERTとCOMMITを行います。これで、アクティブなレコードが重複しています。

    複数の同時挿入/更新トランザクションは、テーブルレベルのロックでのみ機能します。はい、潜在的なスローダウンです。 3つのルール:(1)トランザクションを可能な限り短く保つ、(2)ロックをできるだけ早く解除する、(3)デッドロックを再試行して処理する、

+0

最初のクエリは次のようにしてください: UPDATEテーブルSETステータス= 'INACTIVE' WHERE message = 'New_message' ANDステータス= 'ACTIVE'; – Savash

1

これらのコマンドを両方とも使用してプロシージャを書くことはできますが、挿入トリガを使用して重複をチェックするのが理にかなっています(時間がない場合は夜間ジョブ)。

0

あなたの正確な要件を理解するのは少し難しいです。私はそれを二つの方法を修正してくださいしてみましょう:

  1. あなたは(異なるIDを持つ)テーブル内の同じメッセージを持つエントリの両方をしたい、と(など、非アクティブとしてそれらをマークする)、いくつかのさらなる処理のためのIDを知りたいです。このために、個別のクエリを使用してプロシージャを記述することができます。 1つのクエリでこれを達成できるとは思いません。

  2. あなたはテーブルのいずれのエントリも必要としません(私はこれを「削除したい」から取得しました)。このためには、メッセージがすでに存在するかどうかを確認し、行があれば削除し、そうでなければ挿入する必要があります。私はこれも1つのクエリでは達成できないと考えています。

パフォーマンスが挿入時に制約である場合は、チェックなしで挿入して定期的にデータベースをサニタイズできます。

+0

私が心配している主要な問題は、2つ以上のクエリでこれを実行するときにロックを使用する必要があるということです... – Savash

関連する問題