マルチスレッド プログラムがありますが、各スレッドは実行開始時に MySql 接続プール クラスから 1 つの接続を取得します。次にスレッドは、多数のデータベース テーブル ラッパー クラスを使用して、そのデータベース接続をラッパー クラスに渡すことにより、ビジネス ロジックを実行します。これらのラッパー クラスの操作は必ずしもシーケンシャルではなく、単一のデータベース接続を使用して、これらのラッパー クラスが互いに独立してデータベース テーブルの変更をコミットまたはロールバックできるようにしたいと考えています。私は、MySql がネストされたトランザクションを許可していないことを認識しており、これを達成する方法を見つけていません。どんな助けでも大歓迎です。ありがとう!
5 に答える
スレッドごとにトランザクションをテーブル ラッパーに関連付ける必要があるようです。IOW、トランザクション クラスを作成する必要があります。トランザクション クラスは、トランザクションが開始および終了するときに、接続プールとの間で接続を取得または解放します。
その後、トランザクションはテーブル ラッパーのファクトリになります。トランザクションによって作成されたすべてのテーブル ラッパーは、トランザクションが存在する接続以外にはアクセスできないため、トランザクション内にあります。
これの厄介な部分は、すべてのオブジェクトがデッド オブジェクトにアクセスできないようにすることです。トランザクションがコミットされたときに何かがテーブル ラッパーを再び使用しようとしたときに何が起こるかを処理するには、何らかの形式の SmartPtr が必要になります。
問題を正しく理解している場合、唯一のオプションは、複数のスレッドが単一の接続を共有できるようにする何らかのトランザクションキューを実装することだと思います。各スレッドは、トランザクション内で実行する必要がある「タスク」をキューに追加できます。次に、これらのタスクをキューから取り出し (ここである種の優先順位付けを実装することもできます)、リクエストを開始したスレッドに結果を返す前にそれらをデータベースに送信するプロセスがあります。呼び出し元のスレッドは、結果を受け取るまでブロックされますが、これは理想的ではありませんが、複数のスレッドと複数のトランザクションが本当に必要な場合は、複数の接続なしでそれを行う別の方法がわかりません。
これは、複数のスレッドが単一のリソースを使用する典型的な例です。
解決策は、mysql 接続操作でミューテックスを使用することです。
接続プールがあるから、接続を増やしてみませんか? また、セマフォを使用して同時接続数を制限することもできます。それ以外の場合は、単一の接続をロックするか、クライアント トランザクションを使用する必要があります (フレームワークを使用します。これは単純ではなく、接続が 1 つしかない場合はとにかく接続をロックする必要がありますが、トランザクションがない場合に比べて待機時間は非常に短くなります。コード側で)。
最も簡単な解決策は、スレッドごとに新しい接続を作成することです。これは、Apache/PHP で通常行われている方法です。
書き込みが読み取りよりもはるかに少ない場合 (書き込みが必要なスレッドは 10 スレッド中 1 つだけ)、SELECT に 1 つのグローバル接続を使用し、更新が必要なスレッドごとに新しい接続を作成できます。
その後、書き込みに使用される最大 10 個のスレッドのプールを持つことができます (したがって、最大 10 個の同時トランザクションを持つことができます)。結局のところ、同時実行が必要な場合は、複数の接続が必要です。