2017-01-06 4 views
0

私は、SQL Serverデータベースに接続し、レコードのバッチを循環してさまざまなタスクを実行し、それに応じてデータベースを更新します(つまり、「成功」、「エラー」など)。SQL Serverのロック

私が遭遇している潜在的な問題は、各レコード(長い話)を読むのにおよそ1分かかりますので、複数のユーザーがアプリケーションを実行している場合、「データ衝突または同じ時間に同じレコードを処理しようとしているユーザー。それが適切に実行されることはできません。

最初は、LOCKED列を追加して、アプリケーションが既に別のユーザーによってレコードが開かれているかどうかを判断するのに役立ちましたが、そのアプリケーションがクラッシュしたり、他のユーザーが無期限に開いたそのレコードを表示します...そうですか?または私はここに簡単な解決策がないのですか?

とにかく、アプリケーションが一度に100個のレコードを持つことが可能で、アプリケーションが処理している間にデータベースに「ロックアウト」し、他のユーザーがアプリケーションを実行できるようにするとSELECT重複しないように100の異なるセット。それは可能ですか?私はこの問題についていくつかの調査を試みましたが、SQL Serverでの私の経験は非常に限られています。すべての助けをありがとう!

+0

LOCKED列が十分で、唯一の問題がクラッシュする可能性がある場合は、夜中に実行するマスターロック解除スケジュールされたタスクを追加するだけです。 – SunKnight0

+0

http://blog.sqlauthority.com/2012/11/15/sql-server-concurrency-basics-guest-post-by-vinod-kumar/ –

+0

http://stackoverflow.com/questions/1138026/sql-サーバー・パフォーマンスと、多くの並行-長時間実行-クエリ私はまだ、これは私が探しているものです全くわからないものの、詳細な応答をありがとう –

答えて

2

あなたはキューを作成しようとしているようです。 SQL ServerのWihin、このようなシナリオのための2つの主要なソリューションがあります。

[1] Service Brokerが(参照:活性化、RECEIVE TOP(1)/TOP(100))を

または

[2]テーブルを使用してカスタムキューを開発するには、プラスUPDATE/DELETE/SELECT TOP(100) ... FROM dbo.QueueTable WITH(READPAST, ROWLOCK) 。これらのテーブルヒントの役割は以下の通りです:

  • READPASTref - see READPAST section)(他の同時トランザクションによってロック)すでにロックされたレコード

  • ROWLOCKref - see ROWLOCK section)は(行=レコードレベルでロックを強制的に読書を避けますページ/パーティション/テーブルロックとは対照的に)。さらに、キュー表のレコードを処理しようとしている(そして処理しようとしている)すべてのconcurentスレッドは、同じデータ・アクセス・パターン(READPAST, ROWLOCK)を使用する必要があります。

あなたはここにレムスのブログ記事内の詳細を見つけることがあります。テーブルからの読み込みと処理レコードのhttp://rusanu.com/2010/03/26/using-tables-as-queues/

つのテンプレートを - キューは次のようになります。

SET XACT_ABORT ON 
BEGIN TRY 
-- BEGIN TRAN 

CREATE TABLE #SelectedRecords TABLE (
... 
) 
DELETE TOP(100) FROM dbo.QueueTable WITH(READPAST, ROWLOCK) 
OUTPUT deleted.Col1, deleted.Col2, ... INTO #SelectedRecords (Col1, Cold2, ...); 

... Do something with those 100 records ... 

-- COMMIT 
END TRY 
BEGIN CATCH 
-- IF @@TRANCOUNT > 0 
-- BEGIN 
--  ROLLBACK 
-- END 
END CATCH 

コメント行が国連であればSQL Serverは、キューテーブルからのデータの読み取り中およびデータ処理中に1つのTXを使用します。 1つの例外がキャッチブロックによって傍受された場合、SQL Serverは現在のTXをロールバックします(キューテーブルから読み込まれ、削除された100レコードを含む)。

注:理想的には、データ処理ブロックは、別の/ネストされたTXを開く/作成しないでください。

注意#2:あなたは確認する必要があり、インデックス(またはヒープ構造)がキュー表の支持体上で定義された(またはしない)場合はこのように行ロック:

SELECT i.allow_row_locks, * 
FROM sys.indexes i 
WHERE i.object_id = OBJECT_ID('dbo.QueueTable') 

ノート#3:allow_row_locksビットはその後/ 0 falseの場合

ALTER INDEX index_name 
ON dbo.QueueTable 
REBUILD 
WITH allow_row_locks = ON 
+0

。データ処理であれば、この作品のようなものは、特定のタスクを実行するために、SQL Serverのではなく、サーバー側のコード、例えばPHPを経由して処理されませんでしたか?アイデアは –

+1

...「完了」または「エラー」などとDBを更新し、SQLを経由して一度に100件のレコードをつかむPHPを経由して、レコードをループし、さまざまなタスクを実行し、その後、これらのタスクの結果をもとにすることですはい。それが可能だ。 Service Brokerの場合、いわゆる「外部アクティベータ」(検索キーワード:SQL Serverサービスブローカ外部アクティベータ)があります。キュー表のために私は、次の許可された値を持つ列のステータスを追加します。エラーなしで処理された0新しい、1つの処理、2、-1のエラーで処理を。キューから他の100の項目を取得するために、私はステータス= 1の出力を挿入し –

+1

更新QTトップ(100)を使用します。* dbo.QueueTableからステータス= 0 –

関連する問題