並行性を処理するためのロック—いいアイデア? [閉まっている]

StackOverflow https://stackoverflow.com/questions/225625

  •  03-07-2019
  •  | 
  •  

質問

同時実行の問題を処理するために、ロック-行、テーブル、データベースのロックなど、どのような形式のロックでも良いソリューションですか?

そうでない場合、並行性の問題に対処する方法は?

役に立ちましたか?

解決

オラクルを信じるなら、いや、まったくありません。これは、Oracleがそれを避けるためにかなりの時間を費やしたためです。

問題は、リーダーがライターをブロックできることとライターがリーダーをブロックできることです。ライターは、すべてのリーダーが書き込みを完了する前に行を終了するまで待機する必要があります。そのため、書き込みプロセスとその呼び出し元が遅れます。トランザクションをロールバックする必要がある場合に備えて、排他ロック(書き込み用)はトランザクションの最後まで保持されます。これにより、トランザクションがコミットされるまで、新しい値を参照する他のトランザクションが停止します。

実際には、コンカレントプログラミングの場合と同様に、競合があまり多くない場合、ロックは一般に問題ありません。行/ページ/テーブルの競合が多すぎる場合(データベース全体をロックするデータベースサーバーは多くありません)、トランザクションが同時にではなく順番に実行されます。

Oracleは行のバージョン管理を使用します。行をロックして書き込む代わりに、行の新しいバージョンが作成されます。読み取りを繰り返す必要がある読者は、読み取った行のバージョンを覚えています。ただし、読み取りを記憶しているリーダーが、このトランザクションが読み取った後に別のライターによって更新された行を更新しようとすると、エラーが発生します。これは、失われた更新を停止するためです。行を更新できるようにするには、SELECTがFOR UPDATEであると言う必要があります。その場合、ロックを取得します。一度に1つのトランザクションのみが行の更新を保持でき、競合するトランザクションは待機する必要があります。

SQL Server 2005以降では、行バージョン管理の名前であるスナップショット分離がサポートされています。繰り返しますが、読み取りたばかりのデータを更新する必要がある場合は、更新ロックを要求する必要があります。SQLServerでは、WITH(UPDLOCK)を使用します。

ロックに関する別の問題は、デッドロックの可能性です。これは、2つのトランザクションのそれぞれが他のトランザクションが必要とするリソースのロックを保持する場所、または一般に、トランザクションのサイクルが互いに進行する必要のあるロックを保持する場所です。通常、データベースサーバーはこのデッドロックを検出し、トランザクションの1つを強制終了してロールバックします。その後、操作を再試行する必要があります。同じ行を変更する複数の同時トランザクションがある状況では、デッドロックの可能性があります。行が異なる順序でタッチされると、デッドロックが発生します。データベースサーバーが使用する順序を強制するのは非常に困難です(通常、オプティマイザに最速の順序を選択させたいため、異なるクエリ間で必ずしも一貫しているとは限りません)。

一般に、スレッド処理と同じことをお勧めします-スケーラビリティの問題を引き起こしていることを証明できるまでロックを使用し、最も重要なセクションをロックフリーにする方法を見つけます。

他のヒント

最初に目標を定義する必要があります。同時リクエストの場合、最後のユーザーまたは最初のユーザーを獲得しますか。 データベースのロックは確かに悪い方法です。テーブル/行をできるだけ遅くロックして、できるだけ早くロックを解除してください。

データベースのロック-テーブルまたは行のロックとは対照的に-並行性を処理するのは悪い方法です。並行性は除外されます。

ある種のDMBSロックを自分でコーディングする代わりに、多くの合理的な代替手段があります。何らかの種類のロック(原子アクションなど)が実際に常に発生していることを念頭に置いてください。哲学者と食事をする必要はありません。トランザクションはロックを回避する方法の1つですが、それは主にコミット用です。レコードがダーティであることをマーク/示すフィールドを使用する(ダーティビットパターン)は別の方法です。アトミックアクセス方法でそれを行っていることを確認してください。以前の投稿で参照されているように、この言語には適切なソリューションがありますが、通常はアプリケーション、プロセス間、レベルの同時実行のみをサポートし、データベース内の同時実行は である必要があります。リッチなアプリケーションレイヤーがあると思いたくはありませんでしたが、そうすることで、これを処理する抽象化レイヤーが多数存在することになります。 TopLink by Oracleは無料であり、Hibernateのより堅牢な兄弟であり、どちらも抽象化、ダーティビット、キャッシュ、およびレイジーロックを通じてデータベースの同時実行性の課題を管理するのに役立ちます。学校や個人的なプロジェクトのためにコーディングしているのでない限り、これらを自分で実装したくありません。問題を理解しますが、巨人の肩の上に立ってください。

私はそうは思わない。なぜならそれはずっと「ダウン」しているからだ。アプリケーションがより複雑になります。ほとんどの言語には優れた並行処理のテクニックがあり、それでも最良の方法は並行処理を「ネイティブに」処理できるコードを書くことです。

Javaの同時実行性に関する詳細情報: http://java.sun.com/docs/books/ tutorial / essential / concurrency / index.html

アプリケーションで並行性を処理するつもりですか、それともデータベースで発生している並行性の問題を解決するつもりですか。前者の場合、それは良いアプローチとして私を打つことはありません。後者の場合、これはスキーマを再設計することなくあなたの唯一の答えかもしれません。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top