最初に、テーブルをロックしても、別のセッションがデータに対してSELECT
ステートメントを発行するのを妨げることはありません。私はその後、第2セッションを開始し、データを照会することができます
SQL> lock table foo in exclusive mode;
Table(s) Locked.
テーブルをロックした場合
セッション1では
、すべて私が
SQL> select * from foo;
COL1
----------
1
1
オラクルでは、作家が読者をブロックしないたいと思います別のセッションがテーブル内のデータを照会するのを防ぐことはできません。
あなたが実装しようとしているようなものは、悲観的なロックです。その場合、テーブルをロックするのではなく、処理する特定のエントリをロックするSELECT FOR UPDATE
を実行します。他のすべてのセッションでもSELECT FOR UPDATE
(Oracleのバージョンに応じて、SKIP LOCKED
修飾子および/またはWAIT
修飾子を追加する可能性があります)を実行しようとする限り、これにより、処理中の特定の行がロックされ、2番目のセッションで別の行またはタイムアウトを選択するか、実装の詳細に応じて処理する行が見つからなくなります。テーブルをロックする必要はありません。
ロックを解放する唯一の方法は、ロックを取得したセッション(通常はトランザクションを終了することによって)を取得する方法と、取得したセッションを終了する方法です。クライアントアプリケーションがまだ実行されているが、ロックを解除する、またはセッションを終了するための何もしない場合、ロックは無期限に保持されます。 DBAは明示的にセッションを終了し、トランザクションをロールバックしてロックを解除させてシステムを再び動かす必要があります。クライアントアプリケーションが実行を停止するか、少なくとも応答が停止した場合(私はまだ説明している障害シナリオを明確にしていません)、'SQLNET.EXPIRE_TIME' parameter経由のデッドコネクション検出(DCD)をデータベースレベルで有効にするとクライアントが応答していないと判断し、自動的にセッションを終了し、トランザクションをロールバックしてロックを解除します。
しかし、データを処理するセッションが複数ある場合は、いくつかの形式のオプティミスティック・ロックを使用する方が一般にはるかに望ましいです。そうしないと、ビジネス・ユーザーを再び働かせるために緊急にセッションを見つけて殺すために必然的にDBAが必要となるシステムを設計しているので、それがより多くの介入を必要とします。これは、DBAが楽しんでいるものではなく、ビジネスユーザーが不平を感じるものではありません。単純なオプティミスティック・ロック・スキームはそういうものでしょう。
- 処理するキーと、行が更新された最後の時刻を示す何らかの日付を選択します。
- 他のセッションが同じ行を処理しようとしないように、ステータス列を「処理中」に更新します。
- アプリケーション内のエントリを処理する
- 処理が終了したら、最初の手順で選択したキーと時刻を使用してデータを更新します。 1行を更新すると、そのデータを選択してから変更されたセッションは他にありません。 0行を更新すると、選択してから別のセッションでデータが変更されたことがわかります。
この種のアーキテクチャでは、データベースを照会して、処理されている行を確認したり、ある期間後にステータス列を「未処理」に戻すジョブクライアントが終了していない場合他のセッションが別の行を選択して処理することは、実際的には簡単です。例えば、アプリケーションが数時間凍ってから回復すると、比較的安全です。他のセッションがすでに行を再処理したことが処理されただけで見つかるからです。
このコードは何をしていますか?なぜテーブル全体をロックする必要がありますか? –
@Paradoxyde - コードがテーブルをロックするのはなぜですか? Oracleでテーブルを明示的かつ手動でロックすると便利な状況に遭遇したことはありません。まさに「フリーズ」という意味ですか?別のセッションで保持されているデータベースのロックを取得しようとしていますか?それはデータベースのデッドロックに遭遇しましたか?クライアントマシン上でアプリケーションがクラッシュし、強制終了される必要がありますか?他に何か? –
コードはデータベース内のエントリを選択し、それを "予約"します(ステータスカラムをビジーとしてマークします)。そのクライアントマシンは、データベースの外部にあるオブジェクトに対して操作を実行し、戻ってそれを解放します。私はテーブル全体をロックすることは極端ですが、データベース自体は非常に小さいので、プロセスを遅くすることはありません。これを行う理由は、別のクライアントがSELECTを実行してエントリを「選択」するのを防ぐことで、同じエントリを予約する2つのクライアントを絶対に避けることです。 また、フリーズすると、クライアントアプリケーションが無人で無期限にハングアップすることを意味します。 – Paradoxyde