Nir*_*jar 6 sql-server alter-table tempdb sql-server-2014
我正在运行从 INT 到 BIGINT 的更改列,我的表大小为 250 GB,1 小时后我收到版本存储错误,因为 tempdb 已满。
据我所知,它只需要您的内存页和日志文件,但我不确定 Tempdb。有人可以解释一下这个内部结构吗?
我正在使用读提交隔离。
select
name,
snapshot_isolation_state_desc,
is_read_committed_snapshot_on
from sys.databases
Run Code Online (Sandbox Code Playgroud)
...对于这个数据库返回:
名称:数据库名称 Snapshot_isolation_state_desc :关闭 is_read_committed_snapshot_on : 0
假设我们谈论的是一个普通的ALTER TABLE,而不是通过某个向导完成的操作,该向导执行临时表和重命名技巧或任何类似的操作。
直列数据类型更改可能会导致更新表中的每一行。这取决于所涉及的类型。您必须考虑这一点:表中的行图像只是一包字节,直到引擎以某种方式解释为止。引擎遵循表元数据描述来理解这些字节是什么。元数据会说“从偏移量 12 到偏移量 16 是一个整数,列号为 4。从偏移量 17 到偏移量 19 是一个短整数,列号为 5”等等。现在,当您执行更改列类型的 ALTER 时,元数据将更改。现在是 100 万美元的问题:新的元数据是否会正确描述相同的字节包?如果是,则行 ALTER 是瞬时的,并且表中的所有行保持不变。如果没有,那么所有行必须更新。一个巨大的表将导致一个巨大的更新,所有这些都在一个事务中。此更新可能会耗尽您的资源(例如,日志空间不足)。Shanky 是正确的,这个“更新”可能采用临时表->插入的形式,但这是一个实现细节。
前段时间我写了一篇关于后台 SQL Server 表列的文章,其中展示了其中一些操作是如何发生的,以及它们如何在实际的物理行集元数据中留下证据。
现在,您说执行此操作时版本存储空间不足,即使未启用快照,对吗?版本存储不仅仅用于快照隔离。举一个众所周知的例子,触发器中的 DELETED 伪表由版本存储提供支持。这意味着即使您没有启用快照隔离,也可以使用版本存储。请参阅在 SQL Server 中管理 TempDB:TempDB 基础知识(版本存储:我们为什么需要它?),Sunil 引用了版本存储的 3 个非快照相关用途:触发器、MARS 和在线索引构建。
SQL 2014 不支持联机更改列,并且作为 DDL 操作,它不应该要求触发器和 MARS 的行版本控制。所以恕我直言,它不应该增加版本存储。
在这种情况下,我的主要嫌疑人将是一个可读的次要(这里是黑暗中的一个镜头......)。可读的辅助节点将所有读取映射到快照隔离这一事实是有据可查的。我不记得确切的细节,我可能是错的,但我认为为了使辅助数据库支持快照隔离,主数据库必须使用版本存储。考虑这样一个事实,即次要是主要的 物理副本并且行大小必须匹配。
也许不是答案,但评论太长了。
| 归档时间: |
|
| 查看次数: |
1591 次 |
| 最近记录: |