2009-07-31 12 views
0

は大きな時間を助けが必要です....マルチスレッド&DBレコードロック

私はテーブルに、周り2,000,000レコードを言う、上のいくつかの一括操作を実行する.NETアプリケーションを作成する必要があります。アプリケーションを実行し、できるだけ多くの行を処理しようとする機会があります。私は、アプリケーションの複数のスレッドを持つことができる場合は、一度に2000レコードを取ることができると考えている&それらを処理すると、より多くを処理することができるはずです。しかし、それはデータベースサーバー上でかなり高価になります。私が言ったことから、dbサーバーは肥満なマシンであり、圧力に対処できるはずです。

また、一度に2000行だけを取ることによって、アプリケーションが処理の途中で終了した場合は、どこから取り上げるかが分かります。

だから、私はどのように私はそれが別のスレッドに割り当てることがないように、アプリがそれらの行をロック&行を拾うことができます)

1 ...私が求めています何をされると思いますか?

2)アプリにどのようなインテリジェンスをプログラムして、最後に中断したところで処理を開始できるようにすることができますか?

おかげ

KP

答えて

1

よりもむしろ車輪の再発明は、SQL Serverの統合サービス(SSIS)を使用して、これを行う必要があります。これらのシナリオ、特に2008年のリリースでは高度に最適化されています。

+0

ジョン、これは私が最初にやりたかった方向です。しかし、この会社のDBAはSSISを恐れています。彼らはなぜSSISを使いたくないのかについての確固たる理由はありません。 –

+0

さて、彼らは愚か者です。 SSISは、あなたやDBAが構築する可能性のあるものよりもずっと優れたこれらのシナリオに対して最適化されています。それは話のひとつです。彼らはこれがまだ古いDTSであると考えているかもしれません。その場合、進捗状況に細心の注意を払う必要があります。 –

1

私は、SSISがこのようなシナリオにインテリジェンスをたくさん組み込んでいることに同意します。おそらくあなたの時間を投資するための最良の方法です。

このような問題を記録するには、データを分割する方法があります。私は、物理的なストレージパーティショニング(すなわち、テーブルパーティショニングの追加)ではなく、論理的な、パーティションの処理について話しています。あなたは2ミルを分割する。データアクセスレベルで悪用できるの基準に基づいて、N個のパーティションに記録します。など。索引付きの列を作成し、それぞれのパーティションでそれぞれのプロセッサーをチャーニングするN個のプロセッサーを割り当てます。この考え方は、プロセッサが同じ行にアクセスしようとする際に重複しないようにすることです。 'プロセッサ'はスレッドでも良いし、ThreadPoolが非同期データベースアクセスメソッドを使用する作業項目をキューに入れた方が良い。

大きな問題は、何度も適切なパーティションキーがないことです。強制することにより、およびレコードが現在のプロセッサによって処理するためにロックされているUPDLOCK:

with cte as (
    select top (@batchSize) * 
    from myTable with (rowlock, updlock, readpast) 
    where <record is ready to be processed>) 
update cte 
    set <mark record processing> 
output inserted.* 

トリックは選択に使用されるロックのヒントである:そのような場合、あなたはこのように、アドホック・パーティショニングを行うことができます。 readpastヒントを追加することによって、各プロセッサはすでに他のプロセッサによってロックされているレコードをスキップします。このようにして、各プロセッサは、処理が何であれ、処理するレコードの@batchSizeバッチを取得します。

これらのコメントはすべて、Webサービスコール、紙伝票などの印刷など、データベースの外部にある処理に適用されることを理解することが重要です。処理がすべてデータベース内にある場合は、それを単一のT-SQL更新として表現し、照会オプティマイザにパラレルに照会させます。

+0

ジョン、これは私が最初に行きたかった方向です。しかし、この会社のDBAはSSISを恐れています。彼らはなぜSSISを使いたくないのかについての確固たる理由はありません。 –

0

私はこれを行うだろう:(最初は空)

  • 設定一つのテーブルをメイン行のPKのを保持します。 ( - NTILEまたは複数の読み込みを使用するか、列のブロック)、この選択から、それらを引き渡す1つのスレッド「同じスレッドが行をつかむPKないで(PKs_done_TableからPKを選択)
  • テーブルから何とかを選択
  • PKs_Done_Tableそれを呼び出します実際の処理のために他のスレッドへ

処理スレッド:。

  • が取引開始行の行/ブロックを受け入れ
  • PKks_done_tableに完成した作業を挿入します
  • はトランザクションをコミットします。

これにより、大量のスループットと安全な再起動が可能になります。一度にいくつかのテーブルを未処理にしても問題ありません。そうでない場合は、とにかく再起動することはできません。