今天在开发环境遇到了一个问题,我们发现服务器上的硬盘空间满了,查看了下发现这个盘存放的数据库文件应该是来源一个并非很大的库才对。检查之后发现这个数据库下的某个数据文件占了盘符下70%的空间,而大部分数据都来自某张表。但是即便我删除了该表里面所有的数据,这个数据文件并不会把空间都还给操作系统啊。那就面临一个如何把收缩文件大小的问题了。我最先想到的还是SQL Server下的DBCC SHRINKFILE命令,按道理来讲连续执行两条DBCC SHRINKFILE命令应该是可以达到收缩数据库文件大小的目的的。
第一条命令把文件尾部的页面尽量往文件内部靠前的空闲页面填充,这种适用于数据文件而不适用于日志文件;第二条命令把文件尾部的空白页面截断并还给操作系统。这样看好像便可以达到目的了。但是,这两条命令跑起来太慢了。首先这个文件是100GB大小,使用页面所占空间其实只有十分之一也就是10GB。第二条命令我花了快3个小时都没跑完。而且重要的是,第二条命令会造成blocking的现象。在SHRINKFILE的过程中出现某位同事无法访问某张表存储在该文件中的数据。
USE [YourDB]
GO
DBCC SHRINKFILE (28, NOTRUNCATE);
DBCC SHRINKFILE (28, TRUNCATEONLY);
于是乎我想到了另外一个办法,那就是把数据倒到另外一个盘下的文件(这里需要同一个文件组),然后把这个文件delete掉,ALTER DATABASE修改文件的路径,把文件路径设成原先盘符下的文件,再set database offline,把文件拷贝回原先的盘符,再set database online。这样就大功告成了。这种做法适用于本身文件的实际页面所有空间比例很小,比如我这个例子,百分之十,那用这种办法很好解决。至于说上一种办法,有时间再实验下是否成立。