【问题标题】:Transaction log for temp db is full. How not to use a log?tempdb 的事务日志已满。如何不使用日志?
【发布时间】:2019-03-03 03:10:31
【问题描述】:

我有一个相当繁重的DELETE 操作,它试图删除临时表中在另一个数据库表中没有匹配项的行。

DELETE FROM ##SendRecipients
WHERE Id NOT IN (SELECT RecipientId FROM MyDB.dbo.Results)

大约 10 分钟后,我收到以下错误消息:

数据库“tempdb”的事务日志已满,原因是 'ACTIVE_TRANSACTION'。

我为 tempdb 添加新日志文件的尝试无济于事。现在数据库文件和日志的.ldf 文件(分布在三个驱动器上)一起阻塞了服务器空间。

有没有办法告诉 tempdb 不要使用日志,至少只用于这个操作?似乎无法在 tempdb 中进行太多修改。

在数据库中移动临时表是否有帮助?

【问题讨论】:

  • 如果您要填充临时表,为什么不先确保正确的数据进入我在INSERT 语句中添加NOT EXISTS 子句?
  • 简短回答:否。您不能在 SQLServer(以及大多数 RDBMS-es)中使用日志。至于冗长的答案:这是特定版本版本的SQLServer至关重要的情况
  • @Larnu 你说得有道理。让我试试!
  • 我会寻找:a) DBCC OPENTRAN - 寻找打开的交易,也许有罪魁祸首,b) 检查 it's not a case,c) “在数据库中移动临时表” - 当然可以解决问题,但可能会出现另一个问题

标签: sql-server tsql logging server ssms


【解决方案1】:

首先,您可能不想使用全局临时表。它们的效用非常有限。

要减少日志记录,您可以这样做:

select *
into #SendRecipients2
from #SendRecipients
WHERE Id IN (SELECT RecipientId FROM MyDB.dbo.Results)

哪些应该是最少记录的,或者如果您没有处于显式事务中

while 1=1
begin
   DELETE top (10000) FROM #SendRecipients
   WHERE Id NOT IN (SELECT RecipientId FROM MyDB.dbo.Results)
   if @@rowcount = 0 break;
end 

这将允许为每个语句重用事务日志空间。

另一种选择是使用表变量而不是临时表。从不记录对表变量的修改。

【讨论】:

  • 我会尝试您的两种解决方案并回复您。使用全局临时表会导致麻烦吗?
  • 是的。如果您运行存储过程的两个实例,或使用相同全局临时表名称的任何其他存储过程,它们将相互干扰。
猜你喜欢
  • 2017-11-20
  • 1970-01-01
  • 2019-07-03
  • 1970-01-01
  • 2013-07-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多