9

ネットワーク上で実行されるデスクトップ アプリケーションがあり、すべてのインスタンスが同じデータベースに接続しています。

では、この状況で、同じデータベースに接続されている実行中のすべてのインスタンスで機能するミューテックスを実装するにはどうすればよいでしょうか?

言い換えれば、2 つ以上のインスタンスで同じ関数を同時に実行したくありません。1 つの関数が既に実行されている場合、他のインスタンスはその関数にアクセスできません。


PS: ミューテックスしたくない関数がデータベースを使用しないため、データベース トランザクションは解決しません。データベースについて言及したのは、実行中のインスタンス間で情報を交換するために使用できるからです。

PS2: 関数が完了するまでに約 30 分かかるため、2 番目のインスタンスが同じ関数を実行しようとした場合、コンピューター 'X' が既にその関数を実行しているため、現在実行できないというメッセージを表示したいと考えています。 .

PS3: 関数はクライアント マシンで処理する必要があるため、ストアド プロシージャを使用できません。

4

6 に答える 6

2

データベース トランザクションを探していると思います。トランザクションは、変更を他のすべてのクライアントから分離します。

更新:関数は現在データベースに書き込みを行っていないとおっしゃいました。この関数をミューテックスしたい場合は、現在のミューテックス ホルダーを保存する中央の場所が必要になります。データベースはこれで機能します。現在の所有者のコンピューター名を含む新しいテーブルを追加するだけです。関数を開始する前に、そのテーブルを確認してください。

あなたの質問は混乱を招くかもしれないと思います。ミューテックスは、リソースの保護に関するものでなければなりません。関数がデータベースにアクセスしていない場合、どの共有リソースを保護していますか?

于 2009-11-05T18:48:18.913 に答える
0

コードをトランザクション内 (アプリ内、またはより良い方法) ストアド プロシージャ内に配置し、ストアド プロシージャを呼び出します。トランザクション メカニズムは、呼び出し元間でコードを分離します。

于 2009-11-05T18:50:07.920 に答える
0

逆に、メッセージ キューを考えてみましょう。前述のように、DB は、トランザクションまたはテーブルへのシリアル アクセス (ala MyISAM) のいずれかで、これらすべてを管理する必要があります。

于 2009-11-05T18:52:21.400 に答える
0

過去に私は次のことをしました:

  1. 基本的に function_name と is_running の 2 つのフィールドを持つテーブルを作成します。
  2. どの RDBMS を使用しているかはわかりませんが、ほとんどの場合、更新のために個々のレコードをロックする方法があります。Oracle に基づく疑似コードを次に示します。

    トランスを開始

    SELECT FOR UPDATE is_running FROM function_table WHERE function_name='foo';

    -- ここで実行されているかどうかを確認してください。実行されていない場合は、running を「true」に設定できます。

    UPDATE function_table set is_running='Y' where function_name='foo';

    コミット転送

現在、私は Oracle PSQL のドキュメントを持っていませんが、アイデアはわかります。「FOR UPDATE」句は、読み取り後からコミットまでレコードをロックするため、現在のプロセスがコミットされるまで、他のプロセスはその SELECT ステートメントでブロックされます。

于 2009-11-05T18:55:55.287 に答える
0

Java スタックがある場合は、Terracottaを使用してそのような機能を実装できます。

于 2009-11-05T18:55:56.223 に答える
0

関数が現在データベースを使用していない場合でも、この関数を同期する目的で特定のテーブルの問題を解決できます。詳細は、DB と、分離レベルとロックの処理方法によって異なります。たとえば、SQL Server では、トランザクション分離を反復可能読み取りに設定し、ロック行から値を読み取り、トランザクション内で更新します。関数が完了するまでトランザクションをコミットしないでください。ほとんどのデータベースでは、より単純なトランザクションで明示的なテーブル ロックを使用することもできます。すでにデータベースを使用していることを考えると、これはおそらく最も簡単なソリューションです。

何らかの理由でデータベースに依存したくない場合は、クライアントからの TCP 接続を受け入れる単純なサービスを作成できます。各クライアントは実行の許可を要求し、完了すると応答を返します。サーバーは、一度に 1 つのクライアントのみが実行許可を取得できるようにすることができます。死んだクライアントは最終的に TCP 接続を切断し、適切なキープアライブ設定がある限り検出されます。

Xepoch によって提案されたメッセージ キュー ソリューションも機能します。MSMQ や Java Message Queue などを使用して、実行トークンとして機能するメッセージを 1 つ持つことができます。すべてのクライアントがメッセージをリクエストし、完了したら再投稿します。再投稿する前にクライアントが死亡した場合、デッドロックのリスクがあるため、これを検出するロジックを考案する必要があり、複雑になる可能性があります。

于 2009-11-05T19:16:47.117 に答える