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 也会被保存(提交)。诀窍是回滚到保存点,而不是完全回滚。遵循与异常处理和嵌套事务中相同的模式。请注意,并非每个错误都是可恢复的,某些错误会强制完全回滚(例如,死锁是一个典型示例)。

于 2012-11-09T17:18:10.600 回答
1

这里的答案不是 100% 直截了当:

当它们在每个循环结束时插入时,它们将被添加到内存中的数据页中,如果另一个进程使用 READ UnCOMITTED 或 NO LOCK 运行,那么它们将能够看到这些插入。这称为脏读,READ COMMITED 的默认隔离级别可以防止这种情况,但这也意味着事务将被阻止在此级别下读取它,直到循环完成。

但是,SQL Server 可以随时选择将脏页刷新到磁盘。我的意思是在交易结束之前、交易结束时或交易完成之后。

What is certain, is that the writes will be flushed to the transaction log at the end of the transaction, before the commit. This is how SQL Server gauruntees data will not be lost in the event of the database going down. This is called WAL or Write Ahead Logging.

于 2012-11-09T17:21:59.810 回答