外观
Oracle 日志轮换与归档
概述
Oracle数据库生成多种日志文件,包括告警日志、监听日志、审计日志、跟踪日志等。这些日志文件会随着时间不断增长,如果不进行适当的管理,可能会占用大量磁盘空间,影响数据库性能,甚至导致磁盘空间不足的问题。
日志轮换与归档是日志管理的重要组成部分,通过定期轮换和归档日志文件,可以:
- 控制日志文件大小,避免磁盘空间不足
- 提高日志文件的可读性和可管理性
- 便于日志分析和故障诊断
- 满足合规要求,保留必要的日志记录
- 优化数据库性能,减少I/O开销
日志类型与默认位置
1. 主要日志类型
| 日志类型 | 描述 | 默认位置 | 19c/21c差异 |
|---|---|---|---|
| 告警日志(Alert Log) | 记录数据库关键事件和错误 | $DIAGNOSTIC_DEST/diag/rdbms/$DB_UNIQUE_NAME/$INSTANCE_NAME/trace/alert_$INSTANCE_NAME.log | 无明显差异 |
| 监听日志(Listener Log) | 记录监听器活动 | $ORACLE_HOME/network/log/listener.log | 无明显差异 |
| 审计日志(Audit Log) | 记录数据库安全事件 | $ORACLE_BASE/admin/$DB_UNIQUE_NAME/adump 或 UNIFIED_AUDIT_TRAIL | 21c默认使用统一审计 |
| 跟踪日志(Trace Log) | 记录数据库进程详细信息 | $DIAGNOSTIC_DEST/diag/rdbms/$DB_UNIQUE_NAME/$INSTANCE_NAME/trace/ | 无明显差异 |
| 重做日志(Redo Log) | 记录数据库修改操作 | 数据文件目录 | 无明显差异 |
| 归档日志(Archive Log) | 重做日志的归档副本 | 归档目录 | 无明显差异 |
2. 查看日志位置
sql
-- 查询诊断目的地
SELECT name, value FROM V$PARAMETER WHERE name = 'diagnostic_dest';
-- 查询告警日志位置
SELECT value FROM V$DIAG_INFO WHERE name = 'Alert Log';
-- 查询审计文件目录
SELECT name, value FROM V$PARAMETER WHERE name = 'audit_file_dest';
-- 查询归档日志位置
SELECT DEST_NAME, DESTINATION FROM V$ARCHIVE_DEST WHERE STATUS = 'VALID';日志轮换机制
1. 自动轮换
Oracle数据库对某些日志文件提供自动轮换机制:
告警日志:Oracle 11g及以后版本,告警日志会自动轮换,当文件达到一定大小时,会创建新的日志文件,旧文件重命名为
alert_$INSTANCE_NAME.log.$n跟踪日志:跟踪日志会自动轮换,每个进程的跟踪日志会在进程重启时创建新文件,旧文件保留
归档日志:归档日志会自动生成,每个日志序列对应一个归档文件,文件名包含日志序列信息
2. 手动轮换
对于没有自动轮换机制或需要手动控制的日志文件,可以使用手动轮换的方式:
- 监听日志:使用
lsnrctl set log_status off/on命令轮换 - 审计日志:手动重命名审计日志文件,或使用
DBMS_AUDIT_MGMT包管理 - 自定义日志:手动重命名或使用脚本轮换
3. 日志轮换策略
| 轮换策略 | 描述 | 适用场景 |
|---|---|---|
| 按大小轮换 | 当日志文件达到指定大小时进行轮换 | 告警日志、监听日志 |
| 按时间轮换 | 按固定时间间隔进行轮换,如每天、每周 | 审计日志、跟踪日志 |
| 按事件轮换 | 当发生特定事件时进行轮换,如数据库重启 | 告警日志、跟踪日志 |
| 混合策略 | 结合大小和时间进行轮换 | 所有日志类型 |
各种日志的轮换配置
1. 告警日志轮换
1.1 自动轮换配置
Oracle 11g及以后版本,告警日志自动轮换功能默认启用。可以通过以下参数调整自动轮换行为:
sql
-- 查看告警日志自动轮换配置
SELECT * FROM V$DIAG_INFO WHERE name LIKE '%Alert%';
-- 调整诊断目的地大小限制(如果需要)
ALTER SYSTEM SET diag_adr_enabled = TRUE SCOPE = SPFILE;
ALTER SYSTEM SET diag_max_size = 10G SCOPE = SPFILE;1.2 手动轮换
bash
# 手动轮换告警日志
# 方法1:使用ADRCI工具
adrci
adrci> SHOW HOMES
adrci> SET HOME diag/rdbms/orcl/orcl
adrci> PURGE -age 720 -type alert
# 方法2:手动重命名
ALERT_LOG=$(sqlplus -S / as sysdba << EOF
SELECT value FROM V$DIAG_INFO WHERE name = 'Alert Log';
EOF
)
ALERT_LOG=$(echo $ALERT_LOG | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
# 关闭数据库(可选)
sqlplus / as sysdba << EOF
SHUTDOWN IMMEDIATE;
EOF
# 重命名告警日志
mv $ALERT_LOG $ALERT_LOG.$(date +%Y%m%d%H%M%S)
# 启动数据库(如果之前关闭了)
sqlplus / as sysdba << EOF
STARTUP;
EOF2. 监听日志轮换
2.1 自动轮换
监听日志默认不会自动轮换,需要手动配置或使用脚本进行轮换。
2.2 手动轮换
bash
# 手动轮换监听日志
lsnrctl set log_status off
mv $ORACLE_HOME/network/log/listener.log $ORACLE_HOME/network/log/listener.log.$(date +%Y%m%d)
lsnrctl set log_status on2.3 使用logrotate工具轮换
bash
# 创建logrotate配置文件
cat > /etc/logrotate.d/oracle-listener << EOF
$ORACLE_HOME/network/log/listener.log {
daily
rotate 7
compress
delaycompress
missingok
notifempty
create 640 oracle oinstall
postrotate
$ORACLE_HOME/bin/lsnrctl set log_status off > /dev/null 2>&1
$ORACLE_HOME/bin/lsnrctl set log_status on > /dev/null 2>&1
endscript
}
EOF
# 测试logrotate配置
logrotate -d /etc/logrotate.d/oracle-listener
# 手动执行logrotate
logrotate /etc/logrotate.d/oracle-listener3. 审计日志轮换
3.1 标准审计日志轮换
bash
# 手动轮换标准审计日志
# 重命名审计日志目录中的旧文件
find $ORACLE_BASE/admin/$DB_UNIQUE_NAME/adump -name "*.aud" -mtime +30 -exec mv {} {}.old \;
# 清理过期审计日志
find $ORACLE_BASE/admin/$DB_UNIQUE_NAME/adump -name "*.aud.old" -mtime +7 -delete3.2 统一审计日志轮换
sql
-- 清理统一审计日志
EXEC DBMS_AUDIT_MGMT.SET_LAST_ARCHIVE_TIMESTAMP(
AUDIT_TRAIL_TYPE => DBMS_AUDIT_MGMT.AUDIT_TRAIL_UNIFIED,
LAST_ARCHIVE_TIME => SYSTIMESTAMP - 30
);
EXEC DBMS_AUDIT_MGMT.CLEAN_AUDIT_TRAIL(
AUDIT_TRAIL_TYPE => DBMS_AUDIT_MGMT.AUDIT_TRAIL_UNIFIED,
USE_LAST_ARCH_TIMESTAMP => TRUE
);4. 跟踪日志轮换
4.1 自动轮换
跟踪日志会在进程重启时自动轮换,旧文件会保留。可以通过以下方式管理跟踪日志:
sql
-- 查看跟踪日志位置
SELECT value FROM V$DIAG_INFO WHERE name = 'Diag Trace';
-- 使用ADRCI工具管理跟踪日志
adrci
adrci> SHOW HOMES
adrci> SET HOME diag/rdbms/orcl/orcl
adrci> PURGE -age 24 -type trace
adrci> PURGE -age 168 -type cdump4.2 手动清理
bash
# 手动清理跟踪日志
TRACE_DIR=$(sqlplus -S / as sysdba << EOF
SELECT value FROM V$DIAG_INFO WHERE name = 'Diag Trace';
EOF
)
TRACE_DIR=$(echo $TRACE_DIR | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
# 清理24小时前的跟踪日志
find $TRACE_DIR -name "*.trc" -mtime +1 -delete
find $TRACE_DIR -name "*.trm" -mtime +1 -delete5. 归档日志管理
5.1 归档日志配置
sql
-- 查看归档日志配置
SELECT LOG_MODE FROM V$DATABASE;
SELECT * FROM V$ARCHIVE_DEST WHERE STATUS = 'VALID';
-- 启用归档模式(如果未启用)
ALTER DATABASE ARCHIVELOG;
-- 配置归档日志位置
ALTER SYSTEM SET log_archive_dest_1 = 'LOCATION=/u01/app/oracle/archive' SCOPE = SPFILE;
ALTER SYSTEM SET log_archive_format = '%t_%s_%r.dbf' SCOPE = SPFILE;5.2 归档日志清理
sql
-- 使用RMAN清理归档日志
RMAN target / << EOF
DELETE ARCHIVELOG ALL COMPLETED BEFORE 'SYSDATE-7';
EXIT;
EOF
-- 配置归档日志自动删除策略
ALTER SYSTEM SET log_archive_dest_1 = 'LOCATION=/u01/app/oracle/archive DELETE INPUT' SCOPE = SPFILE;自动化日志轮换
1. 使用Shell脚本自动化
创建一个统一的日志轮换脚本,定期执行所有日志的轮换和清理:
bash
#!/bin/bash
# Oracle日志轮换与清理脚本
# 环境变量设置
export ORACLE_HOME=/u01/app/oracle/product/19.3.0/dbhome_1
export ORACLE_SID=orcl
export PATH=$ORACLE_HOME/bin:$PATH
# 获取数据库名称
db_unique_name=$(sqlplus -S / as sysdba << EOF
set heading off feedback off
SELECT DB_UNIQUE_NAME FROM V$DATABASE;
EOF
)
db_unique_name=$(echo $db_unique_name | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
# 获取实例名称
instance_name=$(sqlplus -S / as sysdba << EOF
set heading off feedback off
SELECT INSTANCE_NAME FROM V$INSTANCE;
EOF
)
instance_name=$(echo $instance_name | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
echo "=== Oracle日志轮换与清理脚本 ==="
echo "执行时间: $(date)"
echo "数据库: $db_unique_name"
echo "实例: $instance_name"
echo ""
# 1. 轮换监听日志
echo "1. 轮换监听日志"
lsnrctl set log_status off
mv $ORACLE_HOME/network/log/listener.log $ORACLE_HOME/network/log/listener.log.$(date +%Y%m%d)
lsnrctl set log_status on
echo "监听日志轮换完成"
echo ""
# 2. 清理审计日志
echo "2. 清理审计日志"
audit_dir=$ORACLE_BASE/admin/$db_unique_name/adump
find $audit_dir -name "*.aud" -mtime +30 -delete
echo "已清理30天前的审计日志"
echo ""
# 3. 清理跟踪日志
echo "3. 清理跟踪日志"
trace_dir=$(sqlplus -S / as sysdba << EOF
set heading off feedback off
SELECT value FROM V$DIAG_INFO WHERE name = 'Diag Trace';
EOF
)
trace_dir=$(echo $trace_dir | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
find $trace_dir -name "*.trc" -mtime +7 -delete
find $trace_dir -name "*.trm" -mtime +7 -delete
echo "已清理7天前的跟踪日志"
echo ""
# 4. 清理告警日志(可选,Oracle会自动轮换)
echo "4. 清理旧告警日志"
alert_dir=$(dirname $(sqlplus -S / as sysdba << EOF
set heading off feedback off
SELECT value FROM V$DIAG_INFO WHERE name = 'Alert Log';
EOF
))
alert_dir=$(echo $alert_dir | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
find $alert_dir -name "alert_${instance_name}.log.*" -mtime +30 -delete
echo "已清理30天前的旧告警日志"
echo ""
# 5. 清理归档日志
echo "5. 清理归档日志"
rman target / << EOF > /dev/null 2>&1
DELETE NOPROMPT ARCHIVELOG ALL COMPLETED BEFORE 'SYSDATE-7';
EXIT;
EOF
echo "已清理7天前的归档日志"
echo ""
echo "=== 日志轮换与清理完成 ==="设置脚本执行权限并添加到crontab:
bash
chmod +x oracle_log_rotation.sh
# 每天凌晨2点执行日志轮换
echo "0 2 * * * $PWD/oracle_log_rotation.sh >> $PWD/oracle_log_rotation.log 2>&1" | crontab -2. 使用Oracle Scheduler自动化
sql
-- 创建日志轮换作业
BEGIN
DBMS_SCHEDULER.CREATE_JOB(
job_name => 'LOG_ROTATION_JOB',
job_type => 'EXECUTABLE',
job_action => '/u01/app/oracle/scripts/oracle_log_rotation.sh',
start_date => SYSTIMESTAMP,
repeat_interval => 'FREQ=DAILY; BYHOUR=2; BYMINUTE=0; BYSECOND=0',
enabled => TRUE,
comments => 'Daily log rotation job'
);
END;
/
-- 查看作业状态
SELECT job_name, enabled, state FROM DBA_SCHEDULER_JOBS WHERE job_name = 'LOG_ROTATION_JOB';19c与21c日志轮换差异
| 特性 | 19c | 21c |
|---|---|---|
| 告警日志轮换 | 自动轮换,默认启用 | 增强的自动轮换,支持更多配置选项 |
| 监听日志轮换 | 需手动配置 | 支持更灵活的轮换策略 |
| 审计日志轮换 | 标准审计需手动配置,统一审计支持自动清理 | 统一审计默认启用,自动清理功能更完善 |
| 跟踪日志轮换 | 自动轮换,旧文件保留 | 优化的跟踪日志管理,支持更细粒度的清理策略 |
| 归档日志管理 | 基本的归档管理功能 | 增强的归档管理,支持更多自动化选项 |
| 日志管理工具 | ADRCI工具基本功能 | 增强的ADRCI工具,支持更多命令和选项 |
差异处理策略
利用增强的自动轮换功能:
- 在21c中,充分利用增强的自动日志轮换功能,减少手动配置
- 配置合理的自动轮换参数,适应21c的新特性
更新自动化脚本:
- 更新日志轮换脚本,支持21c的新日志格式和位置
- 利用21c提供的新命令和工具,简化日志管理
优化清理策略:
- 根据21c的日志增长特点,调整清理策略
- 利用21c优化的清理命令,提高清理效率
监控日志性能:
- 监控21c中日志轮换对数据库性能的影响
- 根据监控结果,调整日志轮换配置
日志轮换最佳实践
1. 制定合理的轮换策略
- 根据日志类型制定策略:不同类型的日志采用不同的轮换策略
- 考虑磁盘空间:根据磁盘空间大小,设置合理的日志保留时间和大小限制
- 考虑合规要求:根据行业监管要求,保留必要的日志记录
- 考虑性能影响:避免在高峰期执行日志轮换,减少对数据库性能的影响
2. 自动化管理
- 使用自动化工具:利用Shell脚本、logrotate、Oracle Scheduler等工具实现自动化日志轮换
- 定期执行:根据日志增长速度,设置合理的轮换频率
- 监控执行结果:监控日志轮换作业的执行情况,确保轮换成功
- 记录执行日志:记录日志轮换的执行日志,便于问题诊断
3. 优化存储管理
- 使用高性能存储:将日志存放在高性能存储上,减少I/O瓶颈
- 分离存储:将不同类型的日志存放在不同的存储设备上,提高管理效率
- 压缩存储:对旧日志进行压缩存储,减少磁盘占用
- 分层存储:将近期日志存放在高性能存储上,将旧日志迁移到低成本存储上
4. 安全管理
- 限制日志访问权限:设置合适的日志文件权限,只允许授权用户访问
- 加密存储:对包含敏感信息的日志进行加密存储
- 防止日志篡改:使用文件完整性监控工具,防止日志被篡改
- 审计日志访问:记录日志文件的访问情况,便于安全审计
5. 监控与告警
- 监控日志大小:实时监控日志文件大小,及时发现异常增长
- 监控磁盘空间:监控日志所在磁盘的空间使用情况,避免磁盘空间不足
- 配置告警机制:当日志文件大小或磁盘空间达到阈值时,发送告警通知
- 定期检查:定期检查日志轮换作业的执行情况,确保日志管理正常
常见问题(FAQ)
1. 日志轮换会影响数据库性能吗?
问题:执行日志轮换操作时,会影响数据库性能吗?
解决方案:
- 日志轮换操作通常是轻量级的,对数据库性能影响较小
- 建议在数据库低峰期执行日志轮换,减少对业务的影响
- 使用自动化工具执行日志轮换,避免手动操作的不确定性
- 优化日志存储,使用高性能存储减少I/O影响
2. 如何确定合适的日志保留时间?
问题:如何确定不同类型日志的合适保留时间?
解决方案:
- 根据行业监管要求,确定合规性保留时间
- 根据业务需求,确定故障诊断所需的日志保留时间
- 根据磁盘空间大小,确定实际可保留的日志时间
- 采用分层保留策略,近期日志保留时间长,旧日志保留时间短
3. 日志文件过大怎么办?
问题:日志文件增长过快,很快达到GB级别,怎么办?
解决方案:
- 检查日志内容,确定日志增长过快的原因
- 调整日志级别,减少不必要的日志记录
- 增加日志轮换频率,缩短日志保留时间
- 优化日志存储,使用更快的存储设备
- 考虑使用日志压缩,减少磁盘占用
4. 如何监控日志轮换作业的执行情况?
问题:如何确保日志轮换作业正常执行,及时发现执行失败的情况?
解决方案:
- 配置作业执行日志,记录作业的执行情况
- 使用Oracle Scheduler的通知功能,作业失败时发送通知
- 监控作业的执行状态,定期检查作业日志
- 配置外部监控工具,监控作业的执行结果
5. 如何处理归档日志过多的问题?
问题:归档日志生成过快,占用大量磁盘空间,怎么办?
解决方案:
- 检查归档日志生成频率,确定是否存在异常
- 优化数据库事务,减少重做日志生成
- 增加归档日志清理频率,缩短归档日志保留时间
- 配置归档日志自动删除策略
- 考虑使用压缩归档日志,减少磁盘占用
- 增加归档存储容量,或使用分层存储
6. 日志轮换后,如何确保日志的连续性?
问题:执行日志轮换后,如何确保日志记录的连续性,避免日志丢失?
解决方案:
- 使用原子操作进行日志轮换,避免日志丢失
- 确保日志轮换过程中,数据库不会写入旧日志文件
- 验证新日志文件是否正常生成,包含轮换后的日志记录
- 保留旧日志文件一段时间,确保数据完整
- 定期检查日志的连续性,确保没有日志丢失
总结
Oracle日志轮换与归档是数据库运维的重要组成部分,通过合理的日志管理,可以控制日志文件大小,避免磁盘空间不足,提高日志的可读性和可管理性,便于故障诊断和合规审计。
在实际运维中,应该:
- 了解不同类型日志的特点和默认位置
- 制定合理的日志轮换策略,根据日志类型和业务需求调整
- 利用自动化工具实现日志轮换,减少手动操作
- 兼顾19c和21c的版本差异,调整日志管理策略
- 遵循最佳实践,优化日志存储和安全管理
- 监控日志轮换作业的执行情况,确保日志管理正常
通过建立完善的日志轮换与归档机制,可以有效管理Oracle数据库的日志文件,确保数据库的安全稳定运行,满足合规要求。
