4

JDBC でトランザクションを処理する従来の方法は、auto-commit を false に設定することのようです。これにより新しいトランザクションが作成され、commit の呼び出しごとに次のトランザクションの開始がマークされます。マルチスレッド アプリでは、スレッドごとに新しい接続を開くのが一般的であることを理解しています。

私は RMI ベースのマルチクライアント サーバー アプリケーションを作成しているので、基本的にサーバーは新しい接続ごとに 1 つのスレッドをシームレスに生成します。トランザクションを正しく処理するには、これらのスレッドごとに新しい接続を作成する必要がありますか? このようなアーキテクチャのコストは法外なものではありませんか?

4

3 に答える 3

5

はい、一般に、スレッドごとに新しい接続を作成する必要があります。オペレーティング システムがスレッドの実行をタイムスライスする方法を制御できないため (独自のクリティカル セクションを定義しているにもかかわらず)、複数のスレッドがその 1 つのパイプにデータを送信しようとしている可能性があります。

同じことがどのネットワーク通信にも当てはまることに注意してください。たとえば、HTTP 接続で 1 つのソケットを共有しようとする 2 つのスレッドがあるとします。

  • スレッド 1 がリクエストを行う
  • スレッド 2 はリクエストを行います
  • スレッド 1 はソケットからバイトを読み取り、無意識のうちにスレッ​​ド 2 の要求から応答を読み取ります

すべてのトランザクションをクリティカル セクションにラップして、開始/コミット サイクル全体で他のスレッドをロックアウトした場合、スレッド間でデータベース接続を共有できる可能性があります。しかし、あなたが JDBC プロトコルについて生来の知識を本当に持っていない限り、私はそうはしません。

ほとんどのスレッドがデータベース接続を必要とする頻度が低い (またはまったく必要ない) 場合、1 つのスレッドを指定してデータベース作業を実行し、他のスレッドにそのスレッドへの要求をキューに入れることができる場合があります。これにより、非常に多くの接続のオーバーヘッドが削減されます。ただし、環境内のスレッドごとに接続を管理する方法を理解する必要があります (または、StackOverflow で別の具体的な質問をしてください)。

更新:コメントであなたの質問に答えるために、ほとんどのデータベース ブランドは単一の接続で複数の同時トランザクションをサポートしていません (InterBase/Firebird は私が知っている唯一の例外です)。

個別のトランザクション オブジェクトを用意して、接続ごとに複数のトランザクションを開始およびコミットできると便利です。しかし、ベンダーは単にそれをサポートしていません。

同様に、JDBC や ODBC などの標準的なベンダーに依存しない API も、トランザクション状態は接続オブジェクトの単なるプロパティであるという同じ仮定をしています。

于 2008-11-14T02:17:49.203 に答える
1

スレッドごとに新しい接続を開くことは一般的ではありません。通常、 c3poライブラリのような接続プールを使用します。

アプリケーションサーバーを使用している場合、またはたとえばHibernateを使用している場合は、ドキュメントを参照すると、接続プールを構成する方法がわかります。

于 2008-11-14T02:25:58.250 に答える
1

同じ接続オブジェクトを使用して複数のステートメント オブジェクトを作成し、これらのステートメント オブジェクトを異なるスレッドで同時に使用できます。JDBC によってインターフェースされる最新の DB のほとんどは、これを行うことができます。したがって、JDBC は次のように同時カーソルを利用できます。ここでは PostgreSQL も例外ではありません。例を参照してください。

http://doc.postgresintl.com/jdbc/ch10.html

これにより、接続が短時間だけ使用される接続プーリングが可能になります。つまり、ステートメント オブジェクトを作成し、その後プールに戻されます。この短時間のプーリングは、JDBC 接続がステートメント操作の並列化も行う場合にのみ推奨されます。それ以外の場合は、通常の接続プーリングがより良い結果を示す可能性があります。いずれにせよ、スレッドは文オブジェクトの操作を続行し、後でそれを閉じることができますが、接続はできません。

1. Thread 1 opens statement   
3. Thread 2 opens statement
4. Thread 1 does something         Thread 2 does something
5. ...                             ...
6. Thread 1 closes statement       ...
                                7. Thread 2 closes statement

上記は自動コミットモードでのみ機能します。トランザクションが必要な場合でも、トランザクションをスレッドに結び付ける必要はありません。すべてのトランザクションに沿ってプーリングを分割し、上記と同じアプローチを使用できます。ただし、これが必要になるのは、ソケット接続の制限のためではなく、JDBC がセッション ID をトランザクション ID と同一視するためです。

私がよく覚えていれば、セッション ID とトランザクション ID が同一視されていない単純化されていない設計の API や製品が存在するはずです。この API では、サーバーがトランザクションを実行する場合でも、単一のデータベース接続オブジェクトを使用してサーバーを作成できます。この API と製品が何であるかを確認して、後で説明する必要があります。

于 2011-10-02T10:02:10.240 に答える