2009-08-25 6 views
1

私は、何百ものビジネスユニットから夜間のレポートを受け取るべきサーバーを開発しています。レポートは現在暗号化されたCSVファイルです。合計で、レポートは後日使用するためにデータベースに保存される毎日500,000〜1,000,000レコードになるはずです。同時バッチ処理でJDBC文キャッシュをバイパスする方法はありますか?

私は、送信ごとにPreparedStatementsのセットを作成しました。これらのステートメントは、実行およびコミットする前に50レコードをバッチするために使用されます。各レコードによって最大20個のデータベース挿入が発生する可能性があります。送信がキューに入れられ、1つずつ処理されるとき、すべてがうまくいきます。

これを同時に実行しようとしたところ、別のスレッドがPreparedStatementsのインスタンスと全く同じインスタンスを取得していることに気付きました。これは

  1. 複数のスレッドは、スレッドのいずれかのデータベースが、それはだ満たしていないときに呼ばれたので
  2. のコミットを行うための時間だと思ったようだとき
  3. バッチが実行されたのと同じバッチにステートメントを追加し、次のような問題を引き起こしましたスレッドの一部として制約が文の一部

を使用する時間がなかった質問は次のとおりです。文キャッシュから既存のものを再利用するのではなく、作成するプリペアドステートメントを強制する方法はありますか?

ない

  • によってデータベースから
  • 落下制約をプールする声明/接続されていないバッチについての個別のデータソースを作成するよりも、状況を処理するための任意のより良い方法がある場合には、注文が

逐次処理を強制的にもう

  • を問題ではないでしょうインサート編集:

    は、スレッドT1およびT2もありましょう問題を明確にしようとしました。 ステートメントS1とS2を用意しましょう。 バッチB1とB2があるとします。

    S1を使用するたびに、B1に追加されます。 S2が使用されるたびに、B2に追加されます。 コミットするとき、S1は外部キー制約ごとにS2の前にコミットされなければなりません。

    • T1はT2が無邪気
    • T1が
    • S1Aを含むT1バッチB2にS2Aを追加文S2を使用して、バッチB1にS1Aを追加文S1を使用して送信を処理
    • 嬉々として伝送を処理するとき

      問題が発生しますs2aを含む

    • T1は、コミットする時刻を決定します。
    • T1コミットバッチB1 contai寧S1A
    • T2は、T2が
    • T1が 'いいえ' と言う
    • データベースS2B、S2AをcontaintingバッチB1をコミットS2B、S2Aを含むバッチB2にS2Bを添加S2を使用
    • S1Bを含むバッチB1にS1Bを添加S1を使用し外部キーで禁止されているs1bの前にs2bがコミットされているためです。

    これは、手動での同期と回答を指摘することで回避できますが、各スレッドのローカルロジックを適用する代わりに、各バッチのサイズを個別に追跡する必要があります。

  • +0

    ベンダー固有の方法を使用して必要な処理を行う必要があります。どのRDBMSで作業していますか? – Juris

    +0

    Aww。それは本当に私が聞きたかったものではありません。現在、テストシステムはApache Derby上で動作します。本番データベースは、Oracle 10gまたはRのいずれかになります。 –

    +0

    両方の回答にアップヴォートを付けると、私の問題を考えるのに役立ちます。私がテストしたときに選択したソリューションを提供します。 –

    答えて

    0

    私の現在のソリューションは、心配停止と共有愛するスタートですバッチ。私はロックが現在のスレッドに授与されたときにバッチとして、N個のレコードのセットを永続Nレコードのセットを解析し

  • intermidiate形式で保存2つの相

    1. を処理アルゴリズムを分割しています

    これにより、並行処理とバッチ処理を順次行うことができます。私は、スレッド間の待ち時間を最小限に抑えるためにスイートスポットを見つけなければなりません。

    スウィートスポットの探索は、2段階のロックスキームの実装につながる可能性があります。すなわち、実際のバッチ実行前にすべてのスレッドが現在のレコードを完了していることを確認してください。

    後者の解決策では、各PreparedStatementのパラメータ設定を同期させる必要があるかもしれませんが、問題が発生するかどうかはテストしていません。そうすべき。

  • 1

    複数のステートメントを1つの接続インスタンスから使用しようとしていますか? IMOでは、あなたが記述した動作には接続プールが推奨されます。代替方法は、手動で同期させることです。

    +0

    ありがとうございます。 各スレッドには1つの接続があります。各接続には複数の文があり、それぞれのSQL文ごとに1つのPreparedStatementインスタンスがあります。各ステートメントにはバッチが含まれています。 ステートメントキャッシングのために、各スレッドには、バッチに問題を引き起こす一意のステートメントセットがありません。 接続プールとステートメントキャッシュは、接続とステートメント準備イベントがほとんどなく、遠くにあるので、実際にここでは役に立ちません。 –

    +0

    まだ問題を理解しようとしています - 問題のステートメントの実行順序ですか? – Everyone

    +0

    私はシナリオの(明確に)いくつかの明確化のための質問を編集しました。実行命令はクラッシュを引き起こす、はい。一方、共有ステートメントとバッチは、地方の州を信頼することを不可能にします。これは、私の考えでは、私のシナリオでは回避可能な/非有益な並行処理を引き起こします。つまり、バッチを実際のスレッドとは別に管理します。 –

    1

    解決方法はベンダーによって異なります。

    コードがサーブレットで実行されている場合、Webアプリケーションでデータソースを設定することで問題を解決できます。私はTomcatの下でOracleドライバを使ってこれを行いましたが、他のアプリケーションサーバも同様の方法で接続プーリングを設定することができます。

    コードがスタンドアロンの場合、ベンダー固有のAPIを使用する必要があります。本番データベースとしてOracleを対象とするように、ここでのOracle JDBCドライバのための簡単な例です:Oracleの10.2 JDBC dev guideを参照して、詳細情報については

    import oracle.jdbc.OracleConnection; 
    
    ... 
    
    public static void disableStatementCaching(java.sql.Connection conn) 
         throws SQLException { 
        ((OracleConnection)conn).setImplicitCachingEnabled(false); 
    } 
    
    ... 
    

    +0

    お返事ありがとうございます。私はベンダー固有のAPIを見ていますが、私はそれらを使用することについて少し懐疑的です。 アプリケーションはサーブレットとして実行されません。 EJB3 @WebService-annotationで定義されているWebサービスとして公開されています。ただし、アプリケーションサーバー定義のデータソースを使用し、それを設定することは完全に可能です。将来の開発者が文キャッシュを有効にすることでパフォーマンスを最適化することになる状況につながる、適切なドキュメントが必要です。 –

    関連する問題