这事儿我上周刚在客户那儿经历了一回,真够呛。你正盯着监控看,突然弹出一条告警:SQL Server 数据库可用空间为 0%。那一瞬间,血压直接拉满。数据库跑不动了,业务系统卡成幻灯片,前台的小姑娘急得直拍桌子,后台的运维兄弟满头大汗翻日志。别慌,这种情况我见过不少,每次都能搞定,关键是要弄清楚“0%”到底代表了什么。它不是世界末日,而是数据库在喊救命。

先说说最常见的“死法”:日志文件失控。SQL Server 有两种文件:数据文件(.mdf)和日志文件(.ldf)。日志文件记录每一次修改,就像账本一样。如果数据库恢复模式设成“完整”,但没人做事务日志备份,账本就会无限膨胀。我见过一个客户,日志文件从 50 GB 长到 200 GB,只用了不到一周。他们当时还没察觉,直到磁盘红了才来找我。打开一看,日志文件占了整个磁盘的 98%,数据文件只占 2%。这种死法最冤,因为根本不是数据多,而是日志没清理。解决办法也简单:先收缩日志文件,然后做个全备,再设定定期的日志备份计划。记住,日志备份不是可选项,而是必选项。
还有一种情况是数据文件真的满了。这种情况更棘手,因为清理空间需要动真格。比如一张历史表存了五年数据,占了几百 GB,但业务部门只查询最近三个月的数据。你不能说删就删,得先跟业务确认哪些数据能归档。我有个老客户,交易表每年增长 30%,但查询量翻倍增长。我们做了分区表,把历史数据搬到慢速存储上,主库只保留最近半年数据。空间瞬间释放了 40%,查询速度也快了。数据文件满的时候,别只想着加磁盘,先看看哪些数据能挪走。加磁盘是治标,数据治理才是治本。
磁盘空间为 0,还有一个容易忽略的原因:tempdb 临时数据库。它就像工作台,SQL Server 处理临时表、排序、重排索引时都会用到。如果业务代码写得糙,比如在循环里反复创建临时表却不删除,tempdb 就会疯长。有一次,一个客户的 tempdb 从默认的 8 GB 涨到 120 GB,直接把磁盘撑爆。排查后发现,有个存储过程在循环里用 SELECT INTO 创建临时表,但循环结束前临时表不会释放。改完代码后,tempdb 稳定在 10 GB 以内。所以,遇到磁盘满了,记得查看 tempdb 的文件大小和使用情况。有时候不是业务数据的问题,而是代码埋的雷。
还有一种场景,虽然不常见,但真要命:索引碎片太多。SQL Server 的索引就像书的目录,目录乱了查书就慢。更麻烦的是,重建索引会占用大量空间。我曾帮一个电商客户处理过:他们的订单表有 20 个索引,其中 5 个碎片率超过 80%。重建这些索引时,SQL Server 需要临时空间来排序,如果磁盘本就不足,重建会直接报错,业务就停摆了。只能先删掉几个不常用的索引,重建完再重新创建。这个教训说明,索引不是越多越好,定期维护索引的同时,也要保证磁盘有足够的缓冲空间——至少预留 10% 的磁盘空间给这类操作。
磁盘空间为 0,有时候不是 SQL Server 的锅,而是其他应用在抢地盘。比如操作系统日志、备份文件放错位置,甚至有人把临时文件丢进了数据盘。我遇到过一个奇葩案例:运维同事把每周的数据库备份直接存到了数据库所在的磁盘,三个月没清理,备份文件占满了剩余空间。更离谱的是,他们还在同一台服务器上装了监控软件,监控日志每小时生成一个,单个 500 MB,一周累计 80 GB。排查磁盘空间时,别只盯着 SQL Server 的文件,用 WinDirStat 或 TreeSize 扫描整个磁盘,看看谁在吃空间。很多时候,罪魁祸首并非数据库本身。
再说个容易被忽视的点:自动增长设置不合理。很多初学者安装 SQL Server 时,把数据文件和日志文件都设为“自动增长”,但增量设得太小。比如每次增长 1 MB,如果数据库每秒写入 100 MB,磁盘 I/O 就全花在文件扩展上。更麻烦的是,文件扩展时如果磁盘空间不足,SQL Server 会报错。我建议把自动增长设成合理的固定值,比如数据文件每次增长 500 MB,日志文件每次增长 200 MB,并设定最大文件大小。这样既避免频繁扩展影响性能,又能给运维留出响应时间。千万别放任无限增长,那是给自己挖坑。
聊聊预防。磁盘空间为 0 完全可以避免。我的做法是:每天监控磁盘使用率,设置告警阈值在 80% 和 90%。一旦超过 90%,立刻启动应急流程:先检查日志文件是否膨胀,再找历史数据归档,看 tempdb 和索引。同时,给数据库文件分配独立的磁盘卷,避免与操作系统、备份文件混用。备份文件单独放一个卷,定期清理旧备份。SQL Server 的维护计划要包含索引重建、统计信息更新和日志备份。把这些自动化后,工作轻松多了。
数据库可用空间为 0,本质上是“管理问题”大于“技术问题”。技术手段能解决一时,但管理机制才能根治。你需要跟业务部门沟通数据生命周期,跟运维团队制定监控和告警流程,跟开发团队规范 SQL 代码。别等到磁盘满了才手忙脚乱,那时候每一个操作都是在走钢丝。我见过太多团队因为忽略这些细节,导致业务中断数小时,甚至数据丢失。记住:磁盘空间不是无限的,只要提前规划,它永远不会成为瓶颈。下次再看到告警,别慌,按我说的步骤走一遍,大概率能搞定。如果真的搞不定——那就加磁盘吧,但加完后记得回来优化。


