同時実行性の問題を処理するために、ロックは、行、テーブル、データベースのいずれのロックでも、優れたソリューションですか?
そうでない場合、並行性の問題を処理する方法は?
同時実行性の問題を処理するために、ロックは、行、テーブル、データベースのいずれのロックでも、優れたソリューションですか?
そうでない場合、並行性の問題を処理する方法は?
オラクルを信じるなら、いいえ、まったくありません。これは、オラクルがそれを回避するために多大な努力を払ったためです。
問題は、リーダーがライターをブロックし、ライターがリーダーをブロックする可能性があることです。ライターは、すべてのリーダーが行の処理を完了するまで待ってから書き込みを行う必要があります。これにより、書き込みプロセスとその呼び出し元が遅延します。排他ロック (書き込み用) は、トランザクションをロールバックする必要がある場合に備えて、トランザクションの最後まで保持されます。これにより、トランザクションがコミットされるまで、他のトランザクションは新しい値を参照できなくなります。
実際には、コンカレント プログラミングの場合と同様に、競合が多すぎない場合、ロックは通常問題ありません。行/ページ/テーブルの競合が多すぎる場合 (DB 全体のロックを行うデータベース サーバーは多くありません)、トランザクションが同時にではなく順番に実行されます。
Oracle は行のバージョン管理を使用します。行をロックして書き込む代わりに、新しいバージョンの行が作成されます。読み取りを繰り返す必要がある読者は、読み取った行のバージョンを覚えています。ただし、読み取りを記憶しているリーダーが、このトランザクションの読み取り後に別のライターによって更新された行を更新しようとすると、エラーが発生します。これは、失われた更新を停止するためです。行を確実に更新できるようにするには、SELECT が FOR UPDATE であることを示す必要があります。これを行うと、ロックがかかります。一度に FOR UPDATE 行を保持できるのは 1 つのトランザクションだけであり、競合するトランザクションは待機する必要があります。
SQL Server 2005 以降では、行バージョン管理の名前であるスナップショット分離がサポートされています。繰り返しますが、読み取ったばかりのデータを更新する必要がある場合は、更新ロックを要求する必要があります。SQL Server では、WITH (UPDLOCK) を使用します。
ロックに関するもう 1 つの問題は、デッドロックの可能性です。これは単に、2 つのトランザクションがそれぞれ、他のトランザクションが必要とするリソースのロックを保持する場所、または一般に、トランザクションのサイクルが相互に進行する必要があるロックを保持する場所です。通常、データベース サーバーはこのデッドロックを検出し、トランザクションの 1 つを強制終了してロールバックします。その後、操作を再試行する必要があります。同じ行を変更する複数の同時トランザクションがある状況では、デッドロックが発生する可能性があります。行が異なる順序でタッチされると、デッドロックが発生します。データベース サーバーが使用する順序を強制するのは非常に困難です (通常、オプティマイザーに最速の順序を選択させる必要がありますが、これは異なるクエリ間で必ずしも一貫しているわけではありません)。
一般に、スレッドと同じことをお勧めします。スケーラビリティの問題を引き起こしていることが証明されるまでロックを使用し、次に最も重要なセクションをロックフリーにする方法を考え出します。
最初に目的を定義する必要があります。同時リクエストの場合、最後のユーザーまたは最初のユーザーのどちらを獲得したいですか。データベースのロックは確かに悪い方法です。テーブル/行をできるだけ遅くロックし、できるだけ早くロックを解除してください。
それはずっと「ダウン」していて、アプリケーションをより複雑にするからです。ほとんどの言語には優れた並行性処理技術があり、それでも最良の方法は、並行性を「ネイティブに」処理できるコードを作成することです。
Javaでの並行性の詳細については、http: //java.sun.com/docs/books/tutorial/essential/concurrency/index.htmlを参照してください。
テーブルや行のロックとは対照的に、データベースのロックは同時実行性を処理するための悪い方法です。並行性を排除します。
ある種の DMBS ロックを自分でコーディングしなければならないことに代わる多くの合理的な方法があります。なんらかのロックが実際には常に行われていることに注意してください (アトミック アクションなど)。必要がなければ、哲学者と食事をしたくありません。トランザクションはロックを回避する 1 つの方法ですが、それは主にコミットのためのものです。レコードがダーティであることをマーク/示すフィールド (ダーティ ビット パターン) を使用することも別の方法ですが、アトミック アクセス方式で行っていることを確認してください。多くの場合、言語には以前の投稿で参照されている適切なソリューションがありますが、言語は通常、アプリケーション、プロセス間、レベルの同時実行のみをサポートし、場合によっては同時実行をサポートする必要があります。データベースで。豊富なアプリケーション レイヤーがあると仮定したくはありませんが、もしそうなら、これを処理する多くの抽象化レイヤーがあります。TopLink by Oracle は無料で、Hibernate のより堅牢な兄弟であり、どちらも抽象化、ダーティ ビット、キャッシング、遅延ロックを通じてデータベースの同時実行の課題を管理するのに役立ちます。学校や個人的なプロジェクトでコーディングする場合を除き、これらを自分で実装したくはありません。問題は理解できますが、巨人の肩の上に立つ必要があります。
アプリケーションで並行性を処理することを意味しますか、それともデータベースで発生している並行性の問題を解決することを意味しますか。前者の場合、それは良いアプローチとして私を襲うことはありません。後者の場合、スキーマをリエンジニアリングせずにこれが唯一の答えになる可能性があります。