小编Hon*_*ger的帖子

插入时磁盘空间已满,会发生什么?

今天我发现存储我的数据库的硬盘已满。这种情况以前发生过,通常原因很明显。通常有一个错误的查询,这会导致对 tempdb 的大量溢出,它会一直增长到磁盘已满。这次发生的事情不太明显,因为 tempdb 不是驱动器满的原因,而是数据库本身。

事实:

  • 通常的数据库大小约为 55 GB,它增长到 605 GB。
  • 日志文件大小正常,数据文件很大。
  • 数据文件有 85% 的可用空间(我将其解释为“空气”:已使用但已释放的空间。一旦分配,SQL Server 将保留所有空间)。
  • Tempdb 大小正常。

我找到了可能的原因;有一个查询选择了太多的行(错误连接会导致选择 110 亿行,而预计会有几十万行)。这是一个SELECT INTO查询,这让我怀疑是否可能发生以下情况:

  • SELECT INTO 被执行
  • 目标表已创建
  • 数据在选择时插入
  • 磁盘已满,导致插入失败
  • SELECT INTO 被中止并回滚
  • 回滚释放空间(删除已插入的数据),但 SQL Server 不会释放释放的空间。

但是,在这种情况下,我不希望 由 创建的表SELECT INTO仍然存在,它应该被回滚删除。我测试了这个:

BEGIN TRANSACTION 
SELECT  T.x
INTO    TMP.test
FROM    (VALUES(1))T(x)

ROLLBACK

SELECT  * 
FROM    TMP.test
Run Code Online (Sandbox Code Playgroud)

这导致:

(1 row affected)
Msg 208, Level 16, State 1, Line 8
Invalid object name 'TMP.test'.
Run Code Online (Sandbox Code Playgroud)

然而目标表确实存在。不过,实际查询并未在显式事务中执行,这能解释目标表的存在吗?

我在这里勾画的假设是否正确?这是可能发生的情况吗?

sql-server insert rollback sql-server-2016 select-into

18
推荐指数
2
解决办法
2732
查看次数