我干数据库运维这行快十年了,见过太多因为日志爆满导致的系统崩溃事故。最惨的一次,凌晨三点被电话吵醒,一家电商平台的数据库日志把磁盘撑爆了,订单写不进去,用户骂声一片。那哥们儿手忙脚乱地删日志,结果删错了文件,直接把数据库挂了,恢复整整用了六个小时。事后复盘发现,这事根本不必走到这一步。日志满了就像家里垃圾桶满了,要么倒掉,要么换个更大的桶,关键是要知道什么时候该倒、怎么倒。

先说最直接的方案:收缩日志文件。SQL Server 可以用 DBCC SHRINKFILE 命令,指定日志文件的 ID 和目标大小。但这里有个坑,很多人以为执行完就完事了,结果日志文件根本收不回去。原因是数据库的恢复模式设成了“完整”,而且从来没做过事务日志备份。完整恢复模式下,日志会一直保留所有事务记录,直到你主动做日志备份。所以正确的操作是:先 BACKUP LOG 数据库名 TO DISK='备份路径',再执行收缩。收缩后你会看到磁盘空间瞬间释放,系统又活了。但这不是长久之计,只是治标不治本。
另一种情况是日志文件本身并不需要那么大,纯粹是因为数据库设计问题。比如有人把恢复模式改成了“简单”,以为这样日志就不会膨胀。结果发现日志还是越涨越大,查了半天才发现有个大事务一直在跑——比如夜间批量更新几百万条数据,这个事务未提交前,日志必须保留所有中间状态。简单恢复模式下,虽然日志不会无限累积,但只要有未提交的事务,日志文件就不能被截断。解决办法很简单:把大事务拆成小批次提交,比如每处理一万条就 COMMIT 一次。这样日志就能及时清理,文件大小也能被控制。
还有个更常见的问题:日志文件所在的磁盘分区本身就太小。我见过一个客户,C 盘只有 20 GB,系统日志、SQL 日志全挤在一起,每次日志一涨,整个服务器就卡死。他们试了各种收缩、备份的方法,最多撑两周又爆了。我的建议是把日志文件迁移到另一个更大的磁盘上。操作并不复杂:先用 ALTER DATABASE 数据库名 MODIFY FILE (NAME=日志逻辑名, FILENAME='新路径') 改路径,然后重启 SQL 服务。迁移后磁盘空间宽裕了,日志再也不用天天盯着。但说实话,这也只是给系统争取点时间,根本问题仍未解决。
说到根本问题,很多公司的数据库管理其实处于“没人管”的状态。日志备份作业没人设,磁盘空间没人监控,等到报警响了才手忙脚乱。我见过最离谱的案例:某公司日志文件已经涨到 200 GB,但实际有效的日志只有 2 GB,剩下的 198 GB 都是垃圾。原因是自动增长设置太离谱,每次增长 10 GB,结果一次大事务后文件直接飙到 200 GB,后续再也没缩回来。解决方案很简单:把自动增长的增量调小,比如每次增长 500 MB 或 1 GB,别让它“一口吃掉”太多空间。同时设置最大文件大小限制,避免无限制膨胀把磁盘撑爆。
还有一种情况,日志满了不是磁盘满了,而是日志文件本身达到了 SQL Server 的硬性限制。比如 SQL Server 2012 及之前版本,日志文件的最大大小是 2 TB。虽然现在云上很少遇到这种限制,但本地部署的老系统偶尔还是会出现。这时你不能单靠收缩或备份来解决,必须先改数据库的恢复模式为“简单”,再手动缩小日志文件。但要注意,改恢复模式会中断日志链,如果需要时间点恢复,这招就别用了。更稳妥的做法是:在业务低峰期,先做一次完整备份,然后切换恢复模式,收缩日志,再切回完整模式,最后再做一次完整备份。这样既释放了空间,又保证了备份链的完整性。
说到底,解决日志满的问题不能只靠事后救火。我建议每个 DBA 或运维人员养成几个习惯:第一,给日志文件所在的磁盘设置监控告警,比如磁盘使用率超过 80% 就发短信或邮件;第二,定期检查数据库的恢复模式和日志备份策略,完整恢复模式下至少每 15‑30 分钟做一次日志备份;第三,定期检查日志文件的自动增长设置,别让它野蛮生长;第四,如果业务允许,可以把恢复模式改成“简单”,省心省力。但要记住,简单恢复模式下无法做时间点恢复,数据丢失的风险需要自行承担。
说句掏心窝子的话:日志满不是技术问题,而是管理问题。你见过哪个大厂的数据库会因为日志满而挂掉的?他们的监控、备份、扩容都做得滴水不漏。我们普通公司资源有限,但至少要把基础工作做好。下次遇到日志满了,先别急着删文件,先想想备份策略是否完善,磁盘规划是否合理,大事务是否需要优化。把这些根源问题解决了,日志满就不再是噩梦。毕竟,数据库崩了,挨骂的永远是我们,老板不会怪日志文件,只会怪我们。


