1

同じテーブルで実行したい 2 つのプロシージャがあります。1 つは生年月日を使用し、もう 1 つは 3 番目のテーブルから取得した名前と姓を更新します。

誕生日を使用して年齢フィールドを更新するものはテーブル全体で実行され、名前と姓を更新するものはキーに基づいて 3 番目のテーブルに表示される行のみを更新します。

だから私は両方を起動し、行き詰まりました!それらのいずれかに優先順位を付ける方法はありますか?について読みnowait、更新のためにスキップをロックしましたが、スキップしたものに戻るにはどうすればよいですか?

これで私を助けてくれることを願っています!!

4

2 に答える 2

0

すべての行の更新と行の小さなセットの更新が異なる順序で行にアクセスしたため、ロックされたと思います。

前者はフル スキャンを使用して最初に Raw A に到達し、次に他の行に進み、最終的に行 B をロックしようとしました。行 A が既にロックされていることがわかった場合は、行 A をロックします。

したがって、修正: まず、常に変更する必要がある age 列を持つことは、本当に悪い考えです。年齢のインデックス作成を可能にするために行われたのかもしれませんが、正しく記述されたクエリを使用して生年月日のインデックスを作成すると、同じレコードを同じようにすばやく見つけることができます。正規化ルールを破り、デッドロック アプリケーションを自分でコーディングすることになりました。更新が必要な行のみを更新していることを願っています。すべての行を更新するわけではありません。

最善の解決策は、その設計上の欠陥を取り除くことです。

あまり良い解決策ではありませんが、異なる時間にクエリを実行するか、DBMS_Lock を使用してクエリの競合を解消し、一度に 1 つのクエリのみを実行できるようにすることです。

于 2013-03-27T23:44:31.003 に答える
0

1 つの可能性は、一度に更新するすべての行をロックすることです。単一の更新ステートメントですべての更新を行うと、これが達成されます。または

Tから何でも選ぶ
   どこ ...
   更新用;

別の解決策は、私が「ゲートキーパー」テーブルと呼んでいるものを作成することです。どちらの手順でも、対象のテーブルを更新する前にGatekeeper テーブルを排他モードでロックする必要があります。2 番目の手順は、最初のコミットが完了するまでブロックされますが、デッドロックは発生しません。11g では、スペースを割り当てずにテーブルを作成できます。

バリエーションは、ゲートキーパーに行を挿入することです。次に、select for update を使用してその行のみをロックします。その後、他の状況でゲートキーパーを使用できます。

于 2013-03-27T20:46:50.503 に答える