1

私は次の構造を持っています:

PROCEDURE A

BEGIN TRANSACTION
    WHILE <loops 20 times>
        BEGIN

         --10 minute script     
         --INSERT a single record into table X

        END
COMMIT TRANSACTION


PROCEDURE B - This is run via the agent every 10 minutes it scans table X for any new entries and if it finds any it sends an e-mail

すべてが正常に実行された場合、20 個の新しいレコードがテーブル X に追加されます。これらのレコードは、20 個のループすべてが成功した場合にのみ X に追加されますか? ループが 5 回目の反復に達してからエラーが発生した場合、最初の 4 つのレコードがコミットされますか?

4

2 に答える 2

4

トランザクションを 10 分間開いたままにしておくのは悪いことです。トランザクションを 10 分間 20 回開いたままにすると、20 倍の悪になります。長期間存続するトランザクションは、非常に大きな損害を与え、ロックとブロック、ログの使用と増大、回復の問題など、深刻な問題を引き起こします。以上のトランザクションを持つものは決して設計しないでください。解決しようとしている根本的な問題を再検討し、根本的に異なる解決策を考え出す時です。

中心的な質問については、トランザクションはそのような反復でセーブポイントを使用できるため、反復 5 で問題が発生してロールバックする必要がある場合でも、反復 1 ~ 4 が保存 (コミット) されます。秘訣は、完全ではなく、セーブポイントまでロールバックすることです。Exception Handling および Nested Transactions と同じパターンに従います。すべてのエラーが回復できるわけではないことに注意してください。一部のエラーは完全なロールバックを強制します (たとえば、デッドロックは典型的な例です)。

于 2012-11-09T17:18:10.600 に答える
1

ここでの答えは 100% 単純ではありません。

これらは、各ループの最後に挿入されるときにメモリ内のデータ ページに追加されます。別のプロセスが READ UnCOMITTED または NO LOCK を使用して実行された場合、これらの挿入を確認できます。これは Dirty Reads と呼ばれ、READ COMMITED のデフォルトの分離レベルはこれを防ぎますが、ループが完了するまで、トランザクションがこのレベルでの読み取りをブロックされることも意味します。

ただし、SQL Server はいつでもダーティ ページをディスクにフラッシュすることを選択できます。これは、トランザクションの終了前、トランザクションの終了時、またはトランザクションの完了後のことを意味します。

確かなことは、コミットの前に、トランザクションの終わりに書き込みがトランザクション ログにフラッシュされることです。これにより、データベースがダウンしても SQL Server 保証データが失われることはありません。これは WAL または Write Ahead Logging と呼ばれます。

于 2012-11-09T17:21:59.810 に答える