这里是我的场景:我们有一个数据库,我们称它为Logging,并带有一个表格,该表格包含来自Log4Net(通过MSMQ)的记录。数据库的恢复模式设置为简单:我们不关心事务日志 - 它们可以翻转。Sql Server:分块删除仍填满事务日志;失败时,所有删除都回滚 - 为什么?
我们有一个工作,它使用来自sp_spaceused的数据来确定我们是否达到了一定的大小阈值。如果超过阈值,我们确定需要删除多少行才能将大小降至该阈值的百分之x。 (顺便说一句,我使用exec sp_spaceused MyLogTable
,TRUE
来获得行数和他们的平均大小的粗略近似值,虽然我不相信这是最好的方式去做,但这是一个不同的问题。 )
然后我尝试块删除(比如说,5000在时间)通过循环到一个存储过程,基本上做了这样的电话:
DELETE TOP (@RowsToDelete) FROM [dbo].[MyLogTable]
,直到我已经删除了需要删除的内容。
问题出在这里:如果我有很多要删除的行,则事务日志文件填满。我可以看它通过运行增长
dbcc sqlperf (logspace)
令我困惑的是,当作业失败时,所有删除的行都会回滚。换句话说,看起来所有的块都被包装在一个隐含的事务中(以某种方式)。
我已经试过明确设置隐式事务,将每个DELETE语句包装在BEGIN和COMMIT TRAN中,但无济于事:要么所有删除的块都成功,要么根本没有。
我知道一个简单的答案是,让您的日志文件足够大,以处理尽可能多的记录,但您仍然可以将其视为单个事务处理?
对不起,如果我错过了一件容易的事情,但我已经看过很多关于日志文件增长,恢复模式等的帖子,我无法弄清楚这一点。
还有一件事:一旦作业失败,日志文件会在回落之前保持在95-100%的满量程。但是,如果我运行
checkpoint
dbcc dropcleanbuffers
它会直接回落到约5%的利用率。
TIA。
Piotr,感谢您的建议秒。事实上,我一直在执行查询分析器的“驱动程序”存储过程。关于外部事务的问题让我想知道,查询分析器默认情况下是否设置了implicit_transactions?我检查了Profilier并没有看到。但是,我将在查询分析器会话中再次尝试使用SET IMPLICIT_TRANSACTIONS OFF,并查看是否有所作为(无论全部或部分是否会在失败时回滚)。当我进行这个测试时,我会重新发布。 谢谢你,Paul – 2010-04-30 19:06:42