DBCC命令是集成在T-SQL内的工具程序,可以完成许多T-SQL语法本身无法执行的任务,用途非常广泛。
可分为几类:
维护:针对数据库、索引、文件组的维护工作。
如dbrepair、dbreindex、indexdefrage、shrinkdatabase、shrinkfile、updateusage等。
1、dbcc dbrepair :只是包含在SQL Server 2000中用于向后兼容的,下一版本的 Microsoft SQL Server 将删除该功能。请避免在新的开发工作中使用该功能,并着手修改当前还在使用该功能的应用程序。
2、dbcc dbreindex、dbcc indexdefrage:下一版本的 Microsoft SQL Server 将删除该功能。请避免在新的开发工作中使用该功能,并着手修改当前还在使用该功能的应用程序。
3、收缩数据库、收缩文件
若要收缩特定数据库的所有数据和日志文件,请执行 DBCC SHRINKDATABASE 命令。若要一次收缩一个特定数据库中的一个数据或日志文件,请执行 DBCC SHRINKFILE 命令。
若要查看数据库中当前的可用(未分配)空间量,请运行 sp_spaceused。
可在进程中的任一点停止 DBCC SHRINKDATABASE 操作,任何已完成的工作都将保留。
收缩后的数据库不能小于数据库的最小大小。最小大小是在数据库最初创建时指定的大小,或是使用文件大小更改操作(如 DBCC SHIRNKFILE 或 ALTER DATABASE)显式设置的最后大小。例如,如果数据库最初创建时的大小为 10 MB,后来增长到 100 MB,则该数据库最小只能收缩到 10 MB,即使已经删除数据库的所有数据也是如此。
运行DBCC SHRINKDATABASE 而不指定NOTRUNCATE 选项或TRUNCATEONLY 选项等价于带NOTRUNCATE 运行 DBCC SHRINKDATABASE 操作,然后再带 TRUNCATEONLY 运行 DBCC SHRINKDATABASE 操作。
要收缩的数据库不必在单用户模式下;其他的用户仍可以在数据库收缩时对其进行工作。这也包括系统数据库。
不能在备份数据库时收缩数据库。反之,也不能在数据库执行收缩操作时备份数据库。
DBCC SHRINKDATABASE 的工作原理
DBCC SHRINKDATABASE 以每个文件为单位对数据文件进行收缩。然而,DBCC SHRINKDATABASE 在对日志文件进行收缩时,它将视为所有的日志文件都存在于一个连续的日志池中。文件始终从末尾开始收缩。
假设名为 mydb 的数据库有一个数据文件和两个日志文件。数据文件和日志文件分别是 10 MB,并且数据文件包含 6 MB 数据。
对于每个文件,数据库引擎都会计算一个目标大小。这就是文件将要收缩到的大小。将 target_percent 与 DBCC SHRINKDATABASE 一起指定时,数据库引擎计算的目标大小是收缩后文件中的target_percent 可用空间大小。例如,如果在收缩mydb 时将target_percent 指定为 25,则数据库引擎将此文件的目标大小计算为 8 MB(6 MB 数据加上 2 MB 可用空间)。因此,数据库引擎将任何数据从数据文件的后 2 MB 中移动到数据文件前 8 MB 的可用空间中,然后对该文件进行收缩。
假设 mydb 的数据文件包含 7 MB 的数据。将 target_percent 指定为 30,以允许将此数据文件收缩到可用空间的 30%。但是,将target_percent 指定为 40 却不会收缩数据文件,因为数据库引擎收缩文件的目标大小不能小于数据当前占用空间大小。您还可以用另一种方法来考虑此问题:所要求的 40% 可用空间加上整个数据文件大小的 70%(10 MB 中的 7 MB),超过了 100%。因为所要求的可用百分比加上数据文件占用的当前百分比大于 100%(多出 10%),所以任何大于 30 的target_size 都不会收缩此数据文件。
对于日志文件,数据库引擎使用 target_percent 来计算整个日志的目标大小;因此,target_percent 是收缩操作后日志中的可用空间大小。之后,整个日志的目标大小转换为每个日志文件的目标大小。
DBCC SHRINKDATABASE 尝试立即将每个物理日志文件收缩到其目标大小。如果虚拟日志中的所有逻辑日志部分都没有超出日志文件的目标大小,则该文件将成功截断,收缩操作完成且不显示任何消息。但是,如果部分逻辑日志位于超出目标大小的虚拟日志中,则数据库引擎将释放尽可能多的空间,并发出一条信息性消息。该消息说明需要执行哪些操作来将逻辑日志移出位于文件末尾的虚拟日志。执行该操作以后,DBCC SHRINKDATABASE 可用于释放剩余空间。有关详细信息,请参阅收缩事务日志。
因为日志文件只能收缩到虚拟日志文件边界,所以不可能将日志文件收缩到比虚拟日志文件更小(即使现在没有使用该文件)。虚拟日志文件的大小在创建或扩展这些日志文件时由数据库引擎动态选择。有关虚拟日志文件的详细信息,请参阅事务日志物理体系结构。
最佳做法
当您计划收缩数据库时,请考虑以下信息:
- 在执行会产生许多未使用空间的操作(如截断表或删除表操作)后,执行收缩操作最有效。
- 大多数数据库都需要一些可用空间,以供常规日常操作使用。如果反复收缩数据库并注意到数据库大小变大,则表明收缩的空间是常规操作所必需的。在这种情况下,反复收缩数据库是一种无谓的操作。
- 收缩操作不会保留数据库中索引的碎片状态,通常还会在一定程度上增加碎片。这是不要反复收缩数据库的另一个原因。
- 除非有特定要求,否则不要将 AUTO_SHRINK 数据库选项设置为 ON。
故障排除
在基于行版本控制的隔离级别下运行的事务可能会阻塞收缩操作。例如,执行 DBCC SHRINK DATABASE 操作时,如果在基于行版本控制的隔离级别下运行的大型删除操作正在进行中,则收缩操作将等到删除操作完成才会收缩文件。出现这种情况时,DBCC SHRINKFILE 和 DBCC SHRINKDATABASE 操作会在第一个小时每五分钟将信息性消息(对于 SHRINKDATABASE 为 5202,对于 SHRINKFILE 为 5203)输出到 SQL Server 错误日志,之后每一个小时输出一次。例如,如果错误日志包含以下错误消息:
DBCC SHRINKDATABASE for database ID 9 is waiting for the snapshot
transaction with timestamp 15 and other snapshot transactions linked to
timestamp 15 or with timestamps older than 109 to finish.
|
这意味着收缩操作被时间戳早于 109 的快照事务阻塞,它是收缩操作所完成的上一事务。它还说明 sys.dm_tran_active_snapshot_database_transactions 动态管理视图中的transaction_sequence_num 或first_snapshot_sequence_num 列包含值 15。如果该视图中的transaction_sequence_num 或first_snapshot_sequence_num 列包含的数字小于收缩操作完成的上一事务 (109),则收缩操作将等待这些事务完成。
若要解决此问题,请执行下列任务之一:
- 终止阻塞收缩操作的事务。
- 终止收缩操作。将保留任何已完成的工作。
- 不执行任何操作,并允许收缩操作等到阻塞事务完成。
DBCC SHRINKFILE 工作原理
可在进程中的任一点停止 DBCC SHRINKFILE 操作,任何已完成的工作都将保留。当 DBCC SHRINKFILE 操作失败时,将引发错误。
要收缩的数据库不必在单用户模式下;收缩文件时,其他用户也可使用该数据库。不必在单用户模式下运行 SQL Server 实例以对系统数据库进行收缩。
收缩日志文件
对于日志文件,数据库引擎使用 target_size 来计算整个日志的目标大小;因此,target_size 是收缩操作后日志中的可用空间大小。之后,整个日志的目标大小转换为每个日志文件的目标大小。DBCC SHRINKFILE 尝试立即将每个物理日志文件收缩到其目标大小。但是,如果部分逻辑日志位于超出目标大小的虚拟日志中,则数据库引擎将释放尽可能多的空间,并发出一条信息性消息。该消息说明需要执行哪些操作来将逻辑日志移出位于文件末尾的虚拟日志。执行这些操作以后,DBCC SHRINKFILE 可用于释放剩余空间。有关详细信息,请参阅收缩事务日志。
因为日志文件只能收缩到虚拟日志文件边界,所以不可能将日志文件收缩到比虚拟日志文件更小(即使现在没有使用该文件)。虚拟日志文件的大小在创建或扩展这些日志文件时由数据库引擎动态选择。有关虚拟日志文件的详细信息,请参阅事务日志物理体系结构。
最佳做法
在计划收缩文件时,请考虑以下信息:
- 在执行会产生许多未使用空间的操作(如截断表或删除表操作)后,执行收缩操作最有效。
- 大多数数据库都需要一些可用空间,以供常规日常操作使用。如果反复收缩数据库并注意到数据库大小变大,则表明收缩的空间是常规操作所必需的。在这种情况下,反复收缩数据库是一种无谓的操作。
- 收缩操作不会保留数据库中索引的碎片状态,通常还会在一定程度上增加碎片。这是不要反复收缩数据库的另一个原因。
故障排除
本部分介绍如何诊断和更正在运行 DBCC SHRINKFILE 命令时可能发生的问题。
文件不收缩如果收缩操作运行时未出现错误,但文件大小看起来没有发生更改,则请执行下列操作之一以验证文件是否有足够的可用空间可供删除:
- 运行以下查询。
SELECT name ,size/128.0 - CAST(FILEPROPERTY(name, 'SpaceUsed') AS int)/128.0 AS AvailableSpaceInMB FROM sys.database_files;
- 运行 DBCC SQLPERF 命令以返回事务日志中使用的空间。
如果可用空间不足,则收缩操作无法进一步减小文件大小。
通常,日志文件看起来不收缩。这通常是由于未截断日志文件的原因造成的。可以通过将数据库恢复模式设置为 SIMPLE 或者通过备份日志然后再次运行 DBCC SHRINKFILE 操作来截断日志。有关详细信息,请参阅事务日志截断和收缩事务日志。
收缩操作被阻塞
在基于行版本控制的隔离级别下运行的事务可能会阻塞收缩操作。例如,执行 DBCC SHRINK DATABASE 操作时,如果在基于行版本控制的隔离级别下运行的大型删除操作正在进行中,则收缩操作将等到删除操作完成才会收缩文件。出现这种情况时,DBCC SHRINKFILE 和 DBCC SHRINKDATABASE 操作会在第一个小时每五分钟将信息性消息(对于 SHRINKDATABASE 为 5202,对于 SHRINKFILE 为 5203)输出到 SQL Server 错误日志,之后每一个小时输出一次。例如,如果错误日志包含以下错误消息:
DBCC SHRINKFILE for file ID 1 is waiting for the snapshot transaction with timestamp 15 and other snapshot transactions linked to timestamp 15 or with timestamps older than 109 to finish. |
这意味着收缩操作被时间戳早于 109 的快照事务阻塞,它是收缩操作所完成的上一事务。它还说明 sys.dm_tran_active_snapshot_database_transactions 动态管理视图中的transaction_sequence_num 或first_snapshot_sequence_num 列包含值 15。如果该视图中的transaction_sequence_num 或first_snapshot_sequence_num 列包含的数字小于收缩操作完成的上一事务 (109),则收缩操作将等待这些事务完成。
若要解决此问题,请执行下列任务之一:
- 终止阻塞收缩操作的事务。
- 终止收缩操作。如果终止收缩操作,则会保留任何已完成的工作。不执行任何操作,并允许收缩操作等到阻塞事务完成。
如何收缩日志文件?
通过删除一个或多个不活动的虚拟日志文件来收缩事务日志,从而减小其物理大小。减小大小操作始终以虚拟日志文件为单位进行。例如,如果有一个 600 MB 的日志文件分为六个 100 MB 的虚拟日志,则该日志文件的大小只能按 100 MB 递减。文件可以减小为 500 MB 或 400 MB,但不能减小为 433 MB 或 525 MB。包含任何活动日志记录的虚拟日志文件(即“活动的虚拟日志文件”)是逻辑日志的一部分,不能将其删除。有关详细信息,请参阅事务日志物理体系结构。
注意: |
---|
创建或扩展日志文件时,数据库引擎动态选择虚拟日志文件的大小。有关详细信息,请参阅事务日志物理体系结构。 |
对于日志文件,当前大小与虚拟日志文件使用的页的总大小相同。但请注意,日志文件不使用这些页。不能释放包含任何逻辑日志部分的虚拟日志文件。如果日志文件中的所有虚拟日志文件都包含逻辑日志部分,则此日志文件不能收缩。日志截断将一个或多个虚拟日志文件标记为非活动之后,才能进行收缩。
收缩文件操作只能删除不活动的虚拟日志文件。如果未指定目标大小,收缩文件操作仅删除文件中最后一个活动虚拟日志文件后面的不活动虚拟日志文件。如果指定目标大小,则给定收缩文件操作仅删除足够多的不活动虚拟日志文件,以接近但不超过目标大小。收缩之后,日志文件通常稍大于目标大小,但永远不会小于目标大小。由于虚拟日志文件的存在,因此很难预测日志文件的实际收缩程度。
在收缩任何文件时,必须从文件的末端开始释放空间。在收缩事务日志文件时,将从日志文件的末端释放足够的虚拟日志文件,以便将日志减小到用户所要求的大小。用户指定的target_size 将圆整为下一个最大的虚拟日志文件边界。例如,如果用户为包含六个 100 MB 虚拟日志文件的 600 MB 的示例文件指定 325 MB 的target_size,则最后两个虚拟日志文件将删除,新的文件大小为 400 MB。
DBCC SHRINKDATABASE 或 DBCC SHRINKFILE 操作会立即尝试将物理日志文件收缩为所要求的大小:
- 如果虚拟日志文件中的逻辑日志未超出 target_size 标记,则释放 target_size 标记之后的虚拟日志文件,并成功完成 DBCC 语句,不显示任何信息。
如果虚拟日志中的逻辑日志超出了 target_size 标记,SQL Server 数据库引擎将释放尽可能多的空间并显示一个信息性消息。该消息告诉您必须执行什么操作来从文件尾部的虚拟日志中删除逻辑日志。执行完该操作后,可以重新发出 DBCC 语句以释放剩余的空间。
--收缩数据库 DBCC SHRINKDATABASE('WC', --要收缩的数据库名称或数据库ID 10 --收缩后,数据库文件中空间空间占用的百分比 ) DBCC SHRINKDATABASE('WC', --要收缩的数据库名称或数据库ID 10, --收缩后,数据库文件中空闲空间占用的百分比 NOTRUNCATE --在收缩时,通过数据移动来腾出自由空间 ) DBCC SHRINKDATABASE('WC', --要收缩的数据库名称或数据库ID 10, --收缩后,数据库文件中空间空间占用的百分比 TRUNCATEONLY --在收缩时,只是把文件尾部的空闲空间释放 ) --收缩文件 DBCC SHRINKFILE(wc_fg8, --要收缩的数据文件逻辑名称 7 --要收缩的目标大小,以MB为单位 ) DBCC SHRINKFILE(wc_fg8, --要收缩的数据文件逻辑名称 EMPTYFILE --清空文件 )
4、报告目录视图中的页数和行数错误并进行更正。这些错误可能导致 sp_spaceused 系统存储过程返回不正确的空间使用报告。
DBCC UPDATEUSAGE ( { database_name | database_id | 0 } [ , { table_name | table_id | view_name | view_id } [ , { index_name | index_id } ] ] ) [ WITH [ NO_INFOMSGS ] [ , ] [ COUNT_ROWS ] ]
参数
database_name | database_id | 0
-
要对其空间使用统计信息进行报告和更正的数据库的名称或 ID。如果指定 0,则使用当前数据库。数据库名称必须符合有关标识符的规则。
- table_name | table_id | view_name | view_id
-
要对其空间使用统计信息进行报告和更正的表或索引视图的名称或 ID。表和视图的名称必须符合标识符规则。
- index_id | index_name
-
要使用的索引的 ID 或名称。如果未指定,语句将对指定的表或视图的所有索引进行处理。
- WITH
-
允许指定选项。
- NO_INFOMSGS
-
取消显示所有信息性消息。
- COUNT_ROWS
-
指定使用表或视图中的行数的当前计数更新 row count 列。
注释
DBCC UPDATEUSAGE 将针对表或索引中的每个分区更正行、已用页、保留页、叶级页和数据页的计数。如果系统表中没有错误,则 DBCC UPDATEUSAGE 不返回数据。如果发现错误,并对其进行了更正,同时没有使用 WITH NO_INFOMSGS,DBCC UPDATEUSAGE 将返回系统表中更新的行和列。
DBCC CHECKDB 已得到增强,可以检测页计数或行计数变为负值的情况。检测到上述问题后,DBCC CHECKDB 的输出会包含一个警告和一个建议,建议运行 DBCC UPDATEUSAGE 解决该问题。
最佳做法
- 从 SQL Server 2000 升级数据库后始终运行 DBCC UPDATEUSAGE。这将更正页计数和行计数并在以后加以保持。
- 对于在 SQL Server 2005 或更高版本中创建的数据库,或曾经使用 DBCC UPDATEUSAGE 更正的已升级数据库,请勿定期运行 DBCC UPDATEUSAGE。由于对大型表或数据库运行 DBCC UPDATEUSAGE 会耗费一定的时间,因此不应使用此语句,除非您怀疑 sp_spaceused 返回了不正确的值。
- 只有数据库的 CREATE、ALTER 或 DROP 语句等数据定义语言 (DDL) 经常受到修改时,才应考虑定期运行 DBCC UPDATEUSAGE(例如,每周运行一次)。
示例
A. 为当前数据库中的所有对象更新页计数或行计数,或同时更新这两者
下面的示例将数据库名称指定为 0
,且 DBCC UPDATEUSAGE
报告当前数据库的已更新页计数或行计数信息。
DBCC UPDATEUSAGE (0); GO |
B. 更新页计数或行计数,或同时更新这两者,并禁止显示信息性消息。
下面的示例将 AdventureWorks2008R2 指定为数据库名称,并禁止显示所有信息性消息。
USE AdventureWorks2008R2; GO DBCC UPDATEUSAGE (AdventureWorks2008R2) WITH NO_INFOMSGS; GO |
C. 为某一表更新页计数或行计数,或同时更新这两者
下面的示例报告 AdventureWorks2008R2 数据库中 Employee
表的已更新页计数或行计数信息。
USE AdventureWorks2008R2; GO DBCC UPDATEUSAGE (AdventureWorks2008R2,"HumanResources.Employee"); GO |
D. 为表中的特定索引更新页计数或行计数,或同时更新这两者
下面的示例指定一个索引名称。
USE AdventureWorks2008R2; GO DBCC UPDATEUSAGE (AdventureWorks2008R2, "HumanResources.Employee", IX_Employee_OrganizationLevel_OrganizationNode); GO |