2013-06-18 16 views
8

このストアドプロシージャは、スケジューラで毎日実行され、データがネットワーク経由で渡されます。このストアドプロシージャが実行され、実行プロセスに沿って突然のネットワークタイムアウトが発生します。これは、ネットワークを介して他のサーバーに送信するすべての行を実行します。 ロールバックトランザクションでループを使用してデータにどのように影響するか


さて、私の問題は次のとおりです。

  • どのようにこれは、ループ内でロールバックトランザクションを呼び出し、データに影響を与えるのだろうか?
  • すべての行を再度読み込み、挿入するためにサーバーに送信するか、実行中に失敗した行を読み取るだけですか?

アドバイスが必要です。ありがとうございました

+0

カーソルの代わりに、トランザクション内の更新が続くだけ挿入してこれをやっている理由は、特定の理由がありますか? – peterm

+0

このテーブルには何千ものデータが格納されているため、この実行中にサーバがビジー状態にならないように、カーソルを置く必要があります。これは悪い習慣ですか? – Androidz

+3

@Androidz - これは、セットとして行うよりも、データベースにもっと多くの仕事をもたらすでしょう。私の経験では、列のチャンクを行うこの神話的な「ベスト・プラクティス」は、トランザクション・ログと表スペースを適切に管理することができないDBAによって広がっています。 – LoztInSpace

答えて

6

begin distributed transactionを試すことができます。 Distributed transactionは、分散トランザクションが2つ以上のサーバーにまたがるように設計されているため、この場合に最適です。トランザクションを使用すると、システムがクラッシュしたり、電源が切れても、システムは引き続き一貫した状態に復旧することができます。

BEGIN DISTRIBUTED TRANSACTION; 

BEGIN TRY 
    //Your code here to create the cursor. 
    While @@Fetch_Status = 0 
    Begin 
     INSERT INTO [server].MyDatabase.dbo.Mytabletobeinserted(UPC,Sale_date) 
                  VALUES(@UPC,@Sale_date) 

     Update t_sale_from_pos 
     set been_sent = 'y' 
     where UPC = @UPC and [email protected]_date 

     Fetch Next from CursorSale into @UPC,@Sale_date 
    END 
    close CursorSale 

    deallocate CursorSale 
END TRY 
BEGIN CATCH 
    close CursorSale 

    deallocate CursorSale 

    IF @@TRANCOUNT > 0 
     ROLLBACK TRANSACTION; 
END CATCH; 

IF @@TRANCOUNT > 0 
    COMMIT TRANSACTION; 
GO 

実際には、分散トランザクションではカーソルを使用する必要はありません。あなたの場合は、一時テーブルを作成して並行性の問題を回避することを検討することをお勧めします。これは、insert文に時間がかかることがあり、データを挿入している間にテーブルが別のユーザによって更新され、その後に発生するupdate文が間違った行を更新する可能性があるためです。

BEGIN DISTRIBUTED TRANSACTION; 

BEGIN TRY 
    CREATE TABLE #LocalTempTable(UPC int,Sale_date datetime) 
    INSERT INTO #LocalTempTable(UPC,Sale_date) 
    SELECT UPC,Sale_date 
    FROM YourTable 

    INSERT INTO [server].MyDatabase.dbo.Mytabletobeinserted(UPC,Sale_date) 
    SELECT UPC,Sale_date 
    FROM #LocalTempTable 

    Update t_sale_from_pos 
    set been_sent = 'y' 
    where EXISTS (SELECT * 
        FROM #LocalTempTable 
        WHERE #LocalTempTable.UPC = t_sale_from_pos.UPC 
         AND #LocalTempTable.Sale_date = t_sale_from_pos.Sale_date) 

END 
END TRY 
BEGIN CATCH 
    IF @@TRANCOUNT > 0 
     ROLLBACK TRANSACTION; 
END CATCH; 

IF @@TRANCOUNT > 0 
    COMMIT TRANSACTION; 
GO 
+0

あなたの永続性と巧みな答えのために+1。 – Devart

+0

@khan koユーザーは、ストアが終了したときにこのストアドプロシージャが実行されるため、何もしません。タイムアウトのようなエラーが発生すると、他のテーブルに正常に挿入されませんか? – Androidz

+0

@Androidz:これがユーザー用であるかバックグラウンドプロセスであるかは関係ありません。問題は、実行されたすべてのSQL文が 'データの一貫性 'を保証する必要があることです。エラーがある場合、最も安全な方法はトランザクションをロールバックすることです。そうしないと、データが不整合な状態になることがあります。 –

3

私はあなたを正しく理解しています。

WHILE @@FETCH_STATUS = 0 BEGIN 

    BEGIN TRY 

      INSERT INTO [server].MyDatabase.dbo.Mytabletobeinserted (UPC, Sale_date) 
      SELECT @UPC, @Sale_date 

      UPDATE dbo.t_sale_from_pos 
      SET been_sent = 'y' 
      WHERE UPC = @UPC 
      AND sale_date = @sale_date 

    END TRY 
    BEGIN CATCH 

      UPDATE dbo.t_sale_from_pos 
      SET been_sent = 'n' 
      WHERE UPC = @UPC 
      AND sale_date = @sale_date 

    END CATCH 

    FETCH NEXT FROM CursorSale INTO @UPC, @Sale_date 

END 

CLOSE CursorSale 
DEALLOCATE CursorSale 
+0

私は自分の投稿に言及したように、ストアドプロシージャがジョブスケジューラ上で実行されるので、エラーを表示する必要はありません。 – Androidz

+0

私は答えから 'PRINT'を削除しました。 – Devart

+0

@Magnusあなたのレビューに感謝します。これを読むのは本当に面白いです: – Devart

1

私はあなたが間違った場所で混乱していると思いますが、ここでは

REFERE @@fetch_status

0 = The FETCH statement was successful.

をだから、フェッチがループが行く成功するまで - CATCHはあなたを助ける必要があります/ TRY @@エラーが発生した場合は、作成されたカーソルのすべての行で終了します。そして、エラーがより多くのアイデアについて..あなたが論理的に正しい、とCursorSaleが適切な場所で、適切に定義されている場合、それは正常に動作します

を発生していない場合は、上記のリンク

から例を参照してください、私は願っていますこれは..

+0

ストアドプロシージャに "n"を "y"に更新する行があるので、処理中にエラーが発生してもそれが "y"に更新されます。私が間違っているなら私を訂正してください。 – Androidz

0

各レコードをループさせる代わりに、チャンクで挿入することをお勧めします。一度に5000件のレコードと同じように、自動化されたジョブであれば、これは実現可能です。

ここに私が見つけたリンクがありますが、基本的には上記のループで毎回トップ5000をやっています。私は、インサートのために各レコードにカーソルを置いて仕事をしていると想像します。おそらく非常に高価です。

http://social.msdn.microsoft.com/Forums/sqlserver/en-US/1b3dbf8d-252f-43c4-80d6-d5724fe912b4/how-to-insert-rows-in-chunk-size

関連する問題