很多初学者一学到 Oracle 控制文件和日志文件就头大,觉得这两个东西太底层,平时也看不见摸不着,即使丢了感觉好像也没什么影响。但真等数据库起不来、报一串 ORA 错误的时候,才意识到这些“隐藏文件”其实撑起了整个数据库的命脉。我这套 Oracle 19c 入门系列写到这里,前面已经讲完了实例、表空间、用户和权限这些相对“看得见”的内容,这一篇就把控制文件和日志文件这两个最容易被忽略、但恰恰是灾难恢复时最关键的部分彻底讲透。
这篇文章适合正在系统学习 Oracle 的 DBA 新人、从开发转运维的同行,以及那些已经踩过控制文件丢失、日志文件损坏坑、希望系统补齐原理的同学。我的目标是让你不仅能看懂官方文档里的概念,更重要的是知道日常该怎么管、出了故障怎么救。
1. 控制文件到底是什么,为什么一丢就崩
1.1 控制文件里到底存了什么
控制文件(Control File)是数据库里一个非常小的二进制文件,默认大小一般在几百 MB 以内,但里面存的信息却极其密集。它相当于数据库的“总账本”,所有关于数据库物理结构的信息都记录在这一个文件里。
具体来说,控制文件里存了这些核心内容:
- 数据库的名称、DBID(Database Identifier),也就是数据库的唯一标识,用 RMAN 恢复时第一步要确认的就是 DBID 是否一致
- 所有数据文件和在线日志文件的位置、名称和大小信息
- 表空间的信息
- 当前日志序列号(Log Sequence Number)和检查点信息(Checkpoint SCN)
- RMAN 备份的元数据信息,如果你用 RMAN 做备份,备份集的位置也会记录在控制文件里
- 数据库创建时间、归档日志的历史记录等
你可以把控制文件理解成电脑主板上的 BIOS 芯片。电脑开机时主板需要 BIOS 来识别硬盘、内存、显卡这些硬件,Oracle 实例启动时也需要控制文件来感知数据库有哪些数据文件、哪些日志文件、当前处于什么状态。没有 BIOS 电脑点不亮,没有控制文件数据库就挂掉,道理完全一样。
1.2 数据库启动为什么绕不开控制文件
Oracle 数据库从关闭状态到正常运行,要经历三个阶段:Nomount、Mount、Open。
- Nomount 阶段只需要参数文件(spfile/pfile),这个阶段启动的是实例本身,也就是 SGA 和后台进程
- Mount 阶段就必须要读取控制文件了。在这个阶段,实例会根据控制文件的内容,把数据库的物理结构加载进来,知道有哪些数据文件和日志文件
- Open 阶段会继续读取数据文件和日志文件,做一致性校验,然后才允许用户访问
所以控制文件一旦丢失或损坏,数据库就永远到不了 Mount 阶段,更别提 Open。你运气好,如果控制文件有多个镜像,数据库还能自动切换;如果所有控制文件都坏了,那就要走重建控制文件的恢复流程,非常麻烦,后面第 5 节我会详细讲恢复步骤。
控制文件还有一个非常坑的特点:它是一个复用性很强的文件,如果数据库结构发生变化(比如加了表空间、加了数据文件),控制文件里的内容就会更新。所以控制文件的备份不能像是普通的冷备份那样拷一次就能用一辈子,而是要经常重新备份,这一点很多新手容易忽略。
2. 控制文件的日常管理与备份实操
2.1 查看控制文件位置与当前内容
先解决最基础的问题:控制文件在哪?怎么知道当前有几个控制文件?
最常用的查询命令有两个:
-- 查看控制文件参数值 SQL> show parameter control_files; -- 或者查动态性能视图 SQL> SELECT name, status FROM v$controlfile;第一条命令可以直接看到参数control_files的值,这个值在 spfile 里维护,列出的是一个逗号分隔的完整路径列表。第二条命令 v$controlfile 可以更直观地看到每个控制文件的路径和状态。正常情况下状态应该是空的,如果出现INVALID或DELETED,说明控制文件不可用或正在被替换。
除了看位置,你还得学会看控制文件里到底存了什么内容。有一个很实用的方法:
-- 转储控制文件内容到跟踪文件 SQL> ALTER SESSION SET EVENTS 'immediate trace name controlf level 12';执行完之后,去数据库的 trace 目录找最新的 .trc 文件,打开就能看到控制文件的完整内容,包括每个数据文件的名称、文件号、SCN 信息、日志文件成员信息、检查点记录等。这个操作在排查数据文件路径错误、SCN 不一致这类问题时非常有用,建议初学者亲手做一次,把里面的结构和 v$controlfile 里的记录对应着看一遍,对理解数据库物理结构会有很大帮助。
2.2 多路镜像与位置调整
Oracle 官方强烈建议控制文件至少要有两份,最好三份,分别放在不同的物理磁盘上,这样可以避免单块磁盘故障导致控制文件全部丢失。Database Configuration Assistant(DBCA)创建数据库的时候默认就会创建三个控制文件,但很多情况下这三个文件都落在同一块磁盘上,只是路径不同,遇到磁盘损坏一样团灭。
所以我这里专门说一下怎么手动调整控制文件的位置,增加镜像。
核心思路是:先把新路径加到control_files参数里,重启实例让 Oracle 在新路径也生成一个控制文件,确认正常后再把旧的、位于危险磁盘上的控制文件从参数中移除。
举个例子,当前控制文件分别是/u01/app/oracle/oradata/PROD/control01.ctl和/u02/app/oracle/oradata/PROD/control02.ctl,我现在想把第二份挪到/backup/control02.ctl,操作如下:
-- 1. 修改参数,加入新路径 SQL> ALTER SYSTEM SET control_files='/u01/app/oracle/oradata/PROD/control01.ctl','/backup/control02.ctl' SCOPE=SPFILE; -- 2. 干净地关闭数据库 SQL> SHUTDOWN IMMEDIATE; -- 3. 操作系统层面把旧控制文件复制到新路径 $ cp /u02/app/oracle/oradata/PROD/control02.ctl /backup/control02.ctl -- 4. 重启数据库 SQL> STARTUP;启动后执行SELECT name FROM v$controlfile;,能列出两个路径就说明切换成功。整个过程要注意一点:修改参数之前,旧控制文件不能删除,必须等新路径的控制文件成功生成后才能清理;修改control_files参数时SCOPE必须指定为SPFILE,因为控制文件路径在数据库运行期间不能动态改变,改内存参数没有意义。如果担心操作中途出错,建议先把参数文件备份一份,CREATE PFILE='/tmp/pfile_bak.ora' FROM SPFILE;,出问题能回滚。
2.3 控制文件备份的两条常用命令
控制文件的备份主要有两条路:一条是备份到二进制文件,一条是备份到 SQL 脚本文件。
二进制备份主要是给恢复用的,路径可以自己指定:
-- 备份控制文件到二进制文件 SQL> ALTER DATABASE BACKUP CONTROLFILE TO '/backup/controlbak_20250101.ctl';这种备份格式和当前控制文件完全一样,恢复的时候直接用备份文件替换损坏的控制文件即可,但是二进制备份有一个局限:它反映的是备份时刻的数据库结构,如果备份之后加了数据文件或表空间,使用这个备份去做恢复,新加的数据文件可能无法被正确识别,恢复过程会变复杂。
所以实际操作中我更推荐第二种方式,备份控制文件到 SQL 脚本,也就是所谓的 trace 文件:
-- 生成重建控制文件的 SQL 脚本 SQL> ALTER DATABASE BACKUP CONTROLFILE TO TRACE AS '/backup/controlfile_createscript.sql';生成的脚本本质上是一段CREATE CONTROLFILE语句,它包含了当前数据库完整的结构信息。万一控制文件全丢了,你不需要手动猜测数据库结构,直接编辑这个脚本、微调一下路径,就能重建控制文件。因此我强烈建议每次数据库结构变更之后,都执行一次备份到 trace 的操作,把脚本和二进制备份一起留档,这是控制文件保护的最后一道防线。
补充一个在 RMAN 里备份控制文件的常用方式,RMAN 会在每次备份数据文件的时候自动记录控制文件的快照信息,你也可以手动执行:
RMAN> BACKUP CURRENT CONTROLFILE;这条命令会把控制文件备份到 RMAN 的备份集里。它和 SQL 方式各有利弊,SQL 方式更直观,RMAN 方式更方便和管理其他备份统一,我一般是两条都会做。
3. 日志文件体系:实例恢复的保险箱
3.1 日志的物理结构:组、成员、序列号
在线日志文件(Online Redo Log)是 Oracle 里另一个极为核心的物理文件。它的作用简单来说就一句话:记录所有数据变更,保证数据库崩溃后不会丢数据。
日志文件的结构有三个层次:日志组(Group)、组内成员(Member)、日志序列号(Sequence)。
一个数据库至少有 2 个日志组,正常生产环境建议 3 到 4 组。每个日志组里可以有一个或多个成员,成员就是实际物理文件,一个组里的多个成员内容完全相同,互为镜像。LGWR(日志写入进程)写日志的时候,会同时往当前组的所有成员里写,任何一个成员损坏,只要还有一个成员完好,数据库就能继续运行。
日志序列号是一个只增不减的整数,每次日志组切换都产生一个新的序列号。归档日志的命名通常都包含这个序列号,比如1_50_1122334455.dbf表示序列号 50 的归档日志。序列号是日志恢复时非常重要的线索,它把所有日志按顺序串成了一条线。
查看日志组和成员的信息用这两个视图:
-- 查看日志组信息:组号、序列号、大小、成员数、状态、是否已归档 SQL> SELECT group#, sequence#, bytes, members, status, archived FROM v$log; -- 查看日志组成员信息:物理路径和状态 SQL> SELECT group#, status, type, member FROM v$logfile;3.2 日志的运转流程:日志切换、检查点、归档
理解日志文件的管理,核心是理解它怎么运转。我尽量讲得通俗一点。
数据库里的数据变更先被写入内存中的数据缓冲区(Buffer Cache),随后由 DBWn(数据库写进程)批量写进数据文件。但是 DBWn 的写入时机是不确定的,它可能落后于实际的数据变更。一旦数据库突然宕机,内存里那些还没落盘的数据就会丢失,怎么办?这就轮到日志文件登场了。
LGWR 进程会在数据变更发生的同时,把变更记录持续写入当前日志组。数据库崩溃后重启时,Oracle 会对比数据文件里的检查点位置和日志文件里的记录,把日志中记录的、还没有写入数据文件的变更重新应用一遍,这个动作叫作前滚(Roll Forward),之后再做回滚(Roll Back)。这就是实例恢复的核心逻辑。
日志文件组是轮流使用的。当前正在写入的组状态是CURRENT,下一组状态是ACTIVE,后续的状态是INACTIVE。LGWR 写满当前组之后,会切换到下一组,这个动作就叫日志切换(Log Switch),切换时刻触发一个检查点,通知 DBWn 把脏数据尽早写入数据文件,让检查点向前推进。
如果数据库处于归档模式,日志切换时另一个进程 ARCn 会把当前组的内容复制到归档日志目录,形成一份永久的日志备份。这样即便在线日志被覆盖了,历史的日志记录仍然可以通过归档日志恢复。
我用一个生活化的例子来帮你理解:日志文件相当于飞机的黑匣子,实时记录飞行的每一个动作。日志切换相当于黑匣子写满一盘磁带后换下一盘。归档模式相当于每换下来的磁带都会永久封存,而不是抹掉重录。飞行正常的时候黑匣子没什么存在感,但真出了事故,它就是唯一的证据来源。
3.3 归档模式与非归档模式的选择
数据库的日志模式只有两种:归档模式(ARCHIVELOG)和非归档模式(NOARCHIVELOG)。
非归档模式下,日志切换后旧日志组会被直接覆盖,历史日志不保留,数据库只能恢复到最近一次备份的状态,无法做实时恢复。测试环境、学习环境用非归档模式可以节省磁盘空间,但生产环境我的建议是毫不犹豫开启归档模式。
归档模式的核心优势有两个:
- 支持在线热备份。非归档模式下最安全的备份方式是关闭数据库后冷备,停机时间长。归档模式下数据库可以持续运行,数据文件备份的同时,所有的日志都被归档保存,恢复到任意时间点成为可能
- 支持基于时间点恢复(Point-In-Time Recovery, PITR)。即使某个人误删了一个表,回到误操作之前的时间点,把数据捞回来
由于开启归档模式需要重启数据库,搭建 Data Guard 等场景也必须在归档模式下进行,所以线上数据库从规划之初就应该把归档模式定下来。
查看当前是否归档模式:
SQL> SELECT log_mode FROM v$database; -- 返回 ARCHIVELOG 或 NOARCHIVELOG SQL> ARCHIVE LOG LIST; -- 这条命令也能直观看到当前模式和归档目录如果当前是非归档模式,切换到归档模式的完整流程是:
-- 1. 干净关闭数据库 SQL> SHUTDOWN IMMEDIATE; -- 2. 启动到 Mount 状态 SQL> STARTUP MOUNT; -- 3. 开启归档模式 SQL> ALTER DATABASE ARCHIVELOG; -- 4. 打开数据库 SQL> ALTER DATABASE OPEN;开启后确认一下归档进程是否正常:
SQL> ALTER SYSTEM ARCHIVE LOG START; SQL> ARCHIVE LOG LIST;实测中切归档模式最常踩的坑就是归档目录空间不足。归档日志的增长速度往往超出预期,如果没有定期清理,归档空间满了以后数据库会直接挂起,这是生产环境比较典型的灾难事故。所以开启归档模式的同时,一定要配置好归档清理策略,或者用 RMAN 定期删除过期的归档日志。
4. 日志文件的日常管理:添加、删除、状态处理
4.1 添加日志组和日志成员
日志组数量不是一成不变的,你可能会遇到需要手工增加日志组或日志成员的场景。
最典型的需求有两个:一是当前日志组数量太少,日志切换频率过高,需要增加组数来降低切换频率;二是某一个日志组成员所在的磁盘有老化隐患,需要给日志组增加一个新成员来做镜像保护。
添加日志组的语法:
-- 添加一个日志组,组号自动分配 SQL> ALTER DATABASE ADD LOGFILE '/u01/app/oracle/oradata/PROD/redo04a.log' SIZE 500M; -- 添加一个包含两个成员的日志组 SQL> ALTER DATABASE ADD LOGFILE GROUP 4 ( '/u01/app/oracle/oradata/PROD/redo04a.log', '/u02/app/oracle/oradata/PROD/redo04b.log' ) SIZE 500M;给现有日志组添加成员:
SQL> ALTER DATABASE ADD LOGFILE MEMBER '/u02/app/oracle/oradata/PROD/redo01b.log' TO GROUP 1;添加日志成员时一定要注意路径的可用性,Linux 下如果目录没有写权限或者文件已经存在,命令会直接报错。而且新增的成员文件在创建的时候默认是空的、状态为INVALID,LGWR 会在下一次写这个日志组的时候把内容写进去,状态随之变为正常,这是正常现象,不用紧张。
关于日志文件大小和组数的设计,有个经验性的估算方法:你可以在业务高峰期观察历史上 24 小时的日志切换次数,如果切换次数超过每小时 4 次,说明日志可能太小了。
举个简单的计算例子:假设数据库高峰期每秒产生 1 MB 的 Redo 量,你希望日志切换频率控制在每 30 分钟一次以内,那么单个日志组的容量至少在 1 MB × 60 秒 × 30 分钟 = 1800 MB,也就是约 2 GB。再打个余量,用 2 GB 或 4 GB 的日志文件就基本合理。当然如果业务容量无法预估,先沿用默认值,再根据 AWR 报告中Redo size和Log file switch等待事件来调整也可以。
4.2 删除日志组与成员的注意事项
删除日志文件和添加不同,需要更加谨慎。数据库对日志组状态有以下硬性要求:
CURRENT状态的日志组不能直接删除,需要先执行ALTER SYSTEM SWITCH LOGFILE切换到下一个组ACTIVE状态的日志组不能直接删除,需要先触发一个检查点把它变成INACTIVE,最简单的方法是ALTER SYSTEM CHECKPOINT- 数据库至少要保留 2 个日志组,删光到只剩 1 个不合法
删除日志组:
-- 删组前先确认状态不是 CURRENT 或 ACTIVE SQL> SELECT group#, status FROM v$log; -- 切换日志,把当前组切走 SQL> ALTER SYSTEM SWITCH LOGFILE; -- 触发检查点,让 ACTIVE 变 INACTIVE SQL> ALTER SYSTEM CHECKPOINT; -- 删除日志组 SQL> ALTER DATABASE DROP LOGFILE GROUP 4;删除日志组成员也有类似的限制,CURRENT组的成员不能删。不过删除成员通常不是为了回收空间,而是为了清理损坏的成员文件,让数据库不再尝试写它。删除后建议在操作系统层面把物理文件移走或改名,否则下次创建同名文件时会冲突。
这里分享一个我踩过的坑:有一次我删除日志组成员时,只是执行了ALTER DATABASE DROP LOGFILE MEMBER,没有在系统层面把物理文件清理掉。结果后来归档进程报错,说日志目录里有个孤儿文件一直占着空间,还影响了同名日志组的重建。所以删除成员的时候,SQL 命令和操作系统文件清理必须配合好,不要留下没有对应关系的孤立文件。
4.3 日志切换与手工归档操作
日志切换在正常情况下是自动完成的,但很多管理操作需要手工切换来配合。比如你准备删除当前日志组,比如你刚创建了一个日志组成员,希望它立刻写入数据以验证有效性,再比如你准备做日志相关的恢复测试。
手工切换的语法:
SQL> ALTER SYSTEM SWITCH LOGFILE;这条命令会让 LGWR 马上停止写当前组,切到下一组。执行完可以观察 v$log 中各个组的状态变化,之前CURRENT的组通常变成ACTIVE,再等待检查点完成后变成INACTIVE。
如果想强制触发多个日志切换,可以用循环执行:
BEGIN FOR i IN 1..5 LOOP EXECUTE IMMEDIATE 'ALTER SYSTEM SWITCH LOGFILE'; END LOOP; END; /这个操作常用于测试归档是否正常、测试日志切换对业务的影响、触发日志组状态变更等场景。
如果需要立即归档当前日志:
SQL> ALTER SYSTEM ARCHIVE LOG CURRENT;这条命令会先做一次日志切换,然后把切换下来的日志归档。它和ALTER SYSTEM SWITCH LOGFILE的区别在于,Switch 只负责切换,归档动作由后台进程自动完成;ARCHIVE LOG CURRENT则更加明确地要求立即归档,适合在做备份之前确保某个时间点之前的日志都已经归档到位。
5. 常见问题与故障恢复实录
5.1 ORA-00312/ORA-00313:日志文件丢失
日志文件丢失是实际工作中出现频率比较高的一类故障。常见报错有:
- ORA-00313: 无法打开日志组 2 的成员
- ORA-00312: 联机日志 2 线程 1 位于 /path/redo02.log
这类报错通常意味着 LGWR 或归档进程访问某个日志成员时失败。处理方式取决于这个日志组的状态和数据库是否还在运行。
情况一:数据库还在运行,只是某一个组成员损坏,而组内还有其他正常成员。这种情况相对温和,你可以直接给这个组添加一个新成员,然后删除损坏的成员,整个过程不影响业务。
-- 给组2添加新成员 SQL> ALTER DATABASE ADD LOGFILE MEMBER '/u01/app/oracle/oradata/PROD/redo02b.log' TO GROUP 2; -- 删除损坏成员 SQL> ALTER DATABASE DROP LOGFILE MEMBER '/u01/app/oracle/oradata/PROD/redo02a.log';情况二:整个日志组都损坏,而且是当前正在使用的组,数据库已经强制关闭或崩溃。这种情况就不能简单添加成员来解决了,因为当前组的日志内容是实例恢复的依据,丢了就丢了,无法补回来。如果数据库能打开但状态不干净,可能需要做不完全恢复,开启数据库时加上RESETLOGS。
如果当前损坏的日志组不是当前组,可以先尝试清空日志组,让它重新初始化:
-- 清空一个非当前日志组,内容会丢失 SQL> ALTER DATABASE CLEAR LOGFILE GROUP 3;如果日志已经归档,清空命令可以直接执行;如果日志未归档,需要加UNARCHIVED关键字:
SQL> ALTER DATABASE CLEAR UNARCHIVED LOGFILE GROUP 3;这个命令会跳过归档直接清空日志,也就意味着这段日志对应的数据变更可能无法通过归档日志来恢复了,执行前一定要确认这个日志组对应的归档是否已经做过备份,否则后续可能造成数据丢失。
5.2 控制文件全部丢失的恢复
控制文件全部丢失虽然是小概率事件,但一旦发生,处理不当很容易手忙脚乱。恢复方式取决于你是否留有控制文件的备份。
如果有二进制备份:
-- 数据库在 Nomount 或 Mount 状态下,用备份文件覆盖损坏的控制文件 $ cp /backup/controlbak_20250101.ctl /u01/app/oracle/oradata/PROD/control01.ctl -- 然后在 SQL*Plus 里尝试挂载数据库 SQL> STARTUP MOUNT;如果备份之后数据库结构没有变化,通常可以顺利打开。如果结构发生了变化,数据库可能会报数据文件不属于同一数据库之类的错误,此时需要借助RECOVER DATABASE USING BACKUP CONTROLFILE来恢复。
如果没有二进制备份,但之前执行过备份到 trace 的操作,那就可以用 trace 脚本快速重建控制文件。找到生成的controlfile_createscript.sql,按数据库当前结构修改其中的数据文件路径、日志文件路径,然后执行:
-- 以 resetlogs 方式重建控制文件并打开数据库 SQL> CREATE CONTROLFILE REUSE DATABASE "PROD" RESETLOGS NOARCHIVELOG 2 MAXLOGFILES 32 3 MAXLOGMEMBERS 4 4 MAXDATAFILES 1024 5 MAXINSTANCES 8 6 MAXLOGHISTORY 908 7 LOGFILE 8 GROUP 1 '/u01/app/oracle/oradata/PROD/redo01.log' SIZE 200M, 9 GROUP 2 '/u01/app/oracle/oradata/PROD/redo02.log' SIZE 200M 10 DATAFILE '...' 11 ;执行完成后再ALTER DATABASE OPEN RESETLOGS;。重建控制文件之后建议立刻做一次全库备份,因为这个版本的日志序列已经被重置,之前的归档日志无法继续衔接,后续恢复只能基于新序列开始。
所以你看,平时执行ALTER DATABASE BACKUP CONTROLFILE TO TRACE这个操作的成本极低,但关键时刻能救命,这一步绝对不要省。
5.3 日志频繁切换的定位与调优
日志频繁切换这个问题我单独拿出来讲,是因为它不像文件损坏那样显眼,但它的危害是慢性的:系统性能整体下降、大量等待事件、业务响应变慢,排查起来也容易走弯路。
日志切换频繁的典型特征是:数据库的告警日志里出现过量的Log file switch (checkpoint incomplete)等待事件。这说明日志切换的节奏超过了 DBWn 写数据文件的能力,检查点无法及时完成,事务在等日志空间。
定位方法通常是这样:
- 查 v$log 里各个日志组的状态,如果看到
ACTIVE状态的组非常多,说明检查点推进慢 - 查 v$log_history 里最近一段时间日志切换的时间间隔
- 看 AWR 报告中
Log file sync、Log file parallel write、Log file switch等等待事件的时间占比
解决办法有几条路:
- 增加日志文件大小。日志太小是最常见的原因,比如 200M 的日志,业务量稍微大一点就写满了
- 增加日志组数量。组数太少,LGWR 没地方切换,就会等待
- 优化检查点参数。
FAST_START_MTTR_TARGET如果设置得过小,会导致检查点过于频繁,写盘压力大 - 归档目录慢。归档进程跟不上时,日志切换后无法快速归档,也会拖慢后续切换
我遇到过的最典型的案例是:一个系统原本日志切换 30 分钟一次,某次升级后业务量翻倍,日志还是原来的 200M,切换频率直接变成每 2 分钟一次,应用的Log file sync等待时间飙升。后来把日志改成 2G、组数从 3 组加到 4 组,切换频率立刻降到 1 小时以上,整体性能明显改善。
优化日志切换这件事,本质上是在日志大小、检查点频率、归档能力之间找平衡。日志太大,崩溃恢复的时间会变长;日志太小,频繁切换本身也会浪费性能。所以不建议一味调大,而是在监控数据的基础上反复调整到合理区间。
上面这些操作和案例,都是我这些年实际处理过的场景。控制文件和日志文件的管理短期内看起来都是些琐碎的命令,但灾难发生时这些琐碎的知识就是保命的工具。我个人建议,初学者最好在虚拟机里把控制文件损坏、日志文件丢失、切换归档模式这些故障都亲手演练一遍,练过之后你对数据库的敬畏感和信任感都会完全不同。日常运维里养成一个习惯:每次结构性变更后,同步备份控制文件到 trace,定期检查日志切换频率和归档目录空间,这两件事虽然不起眼,但绝对是性价比最高的预防措施。