1

これが私のシナリオです。Log4Netからのレコードを(MSMQ経由で)保持するテーブルを持つデータベースがあり、それをLoggingと呼びましょう。dbのリカバリモードはSimpleに設定されています。トランザクションログは気にせず、ロールオーバーできます。

sp_spaceusedのデータを使用して、特定のサイズのしきい値に達したかどうかを判断するジョブがあります。しきい値を超えた場合、サイズをそのしきい値のxパーセントに下げるために削除する必要のある行数を決定します。(余談ですが、行数と平均サイズの概算を取得するためにexec sp_spaceusedを使用していますが、それが最善の方法であるとは確信していません。しかし、それは別の問題です。 MyLogTableTRUE

次に、基本的にこれを行うsprocへの呼び出しをループすることにより、削除をチャンク化しようとします(たとえば、一度に5000)。

DELETE TOP (@RowsToDelete) FROM [dbo].[MyLogTable]  

削除する必要があるものを削除するまで。

問題は次のとおりです。削除する行がたくさんある場合、トランザクションログファイルがいっぱいになります。走ることで成長するのを見ることができます

dbcc sqlperf (logspace)  

私が困惑しているのは、ジョブが失敗すると、削除されたすべての行がロールバックされることです。言い換えると、すべてのチャンクが(どういうわけか)暗黙のトランザクションでラップされているように見えます。

暗黙のトランザクションを明示的にオフに設定し、各DELETEステートメントをBEGINおよびCOMMIT TRANでラップしようとしましたが、役に立ちませんでした。削除されたチャンクがすべて成功するか、まったく成功しません。

簡単な答えは、ログファイルを、削除する可能性のある最大数のレコードを処理するのに十分な大きさにすることですが、それでも、これが単一のトランザクションとして扱われるのはなぜですか。

簡単なことを見逃してしまったら申し訳ありませんが、ログファイルの増加やリカバリモードなどに関する投稿をたくさん見てきましたが、これがわかりません。

もう1つ、ジョブが失敗すると、ログファイルは約95〜100%の状態でしばらくの間、ドロップバックする前に保持されます。しかし、私が実行した場合

checkpoint
dbcc dropcleanbuffers

使用率は約5%に戻ります。

TIA。

4

2 に答える 2

0

単純復旧モデルのログ ファイルは、一般的にチェックポイントごとに自動的に切り捨てられます。ループの最後に行うようにチェックポイントを手動で呼び出すことができますが、繰り返しごとに行うこともできます。デフォルトでは、チェックポイントの頻度は、回復間隔の設定に基づいて SQL Server によって自動的に決定されます。

「すべての削除がロールバックされる」限り、外部トランザクション以外の説明はありません。ログをクリーンアップするコード全体を投稿できますか? このコードをどのように呼び出しますか? 暗黙のトランザクションの設定は何ですか?

うーん..ログが大きくなり、自動的に切り捨てられない場合は、ループの外で実行されているトランザクションがあることを示している可能性もあります。select @@trancountループの前に、そしておそらく各反復で何が起こっているのかを知ることができますか?

于 2010-04-30T18:17:31.333 に答える
0

いくつかのことを試しましたが、それでもすべての削除がロールバックされます。@@TRANCOUNT削除の前後にprintintを追加したところ、カウントがゼロになりました。それでも、失敗すると、すべての削除がロールバックされます....SET IMPLICIT_TRANSACTIONS OFFいくつかの場所に追加しました(クエリアナライザからの最初の呼び出し内を含むが、それは役に立たないようです.これは、呼び出されているストアドプロシージャの本体です(私は@RowsToDelete5000 と 8000 に設定しました):

  SET NOCOUNT ON;
  print N'@@TRANCOUNT PRIOR TO DELETE: ' + CAST(@@TRANCOUNT AS VARCHAR(20));

  set implicit_transactions off;
  WITH RemoveRows AS 
  (
    SELECT ROW_NUMBER() OVER(ORDER BY [Date] ASC) AS RowNum
    FROM [dbo].[Log4Net]
  )

  DELETE FROM RemoveRows
  WHERE RowNum < @RowsToDelete + 1

  print N'@@TRANCOUNT AFTER DELETE: ' + CAST(@@TRANCOUNT AS VARCHAR(20));

この t-sql から呼び出されます。

WHILE @RowsDeleted < @RowsToDelete
BEGIN
 EXEC [dbo].[DeleteFromLog4Net] @RowsToDelete 
 SET @RowsDeleted = @RowsDeleted + @RowsToDelete
 Set @loops = @loops + 1
 print 'Loop: ' + cast(@loops as varchar(10))
END

私は困惑していることを認めなければなりません。私はDBの第一人者ではありませんが、これを理解するのに十分理解していると思いました....

于 2010-05-03T16:51:43.060 に答える