ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

Oracle数据库巡检实战:从实例进程到自动化报表的完整方案

Oracle数据库巡检实战:从实例进程到自动化报表的完整方案 简介这份《数据库巡检方案》文档面向Oracle DBA、运维工程师及需要承担数据库日常巡检任务的技术人员围绕实例与后台进程检查、文件系统空间监控、运行日志与监听日志清理、性能指标观察、备份恢复验证、权限安全核查及初始化参数调整等环节整理出一套可落地的巡检思路与操作参考。资源包共1个docx文件约2MB内容以命令示例与检查要点为主便于直接对照执行。文档中涉及通过环境变量确认实例SID、使用df或bdf查看磁盘剩余空间、关注根目录与备份目录容量、清理bdump、cdump、udump及监听日志、查看alert告警日志、核对RMAN备份结果等具体场景并强调保留近期错误信息、设置日志滚动机制等策略。已有136人学习适合希望建立规范巡检流程、快速排查隐患并保障数据库稳定运行的读者参考。1. 从一次凌晨告警说起这份 Oracle 巡检方案到底能解决什么凌晨两点/archivelog挂载点使用率冲到 96%归档写不进去数据库直接挂起。事后复盘发现bdump下的alert_UWNMS1.log已经涨到几百兆udump里堆了几十个core转储文件没人清理。这类事故不是技术难题是巡检没做到位。这份《数据库巡检方案.docx》就是一套面向 Oracle 单实例和 RAC 的日常巡检操作手册覆盖实例与后台进程确认、文件系统空间检查、运行日志清理、备份有效性验证、表空间与失效索引排查、CRS 状态检查、主机性能采集七个环节。它不依赖任何商业监控平台全部用操作系统命令加 SQL 脚本完成适合中小规模 Oracle 环境里没有专职 DBA、由运维或开发兼管的场景。下面按「先确认实例活着、再看空间够不够、然后查备份和对象、最后落到自动化」的顺序拆开讲。2. 实例与后台进程确认巡检的第一刀切在哪2.1 为什么先查实例而不是先看告警日志很多人一上服务器就tail alert.log这个顺序是反的。如果实例本身没起来告警日志可能根本没在写你看到的最后几行是几天前的旧记录容易误判。正确做法是先确认当前会话连的是哪个实例再确认后台进程是否齐全。Oracle 的后台进程里SMON负责实例恢复和空间回收PMON负责清理失败进程DBWn负责脏块写盘LGWR负责写 redoCKPT负责检查点。这几个进程缺任何一个数据库都不算健康。$env | grep SID只能告诉你环境变量指向哪个 SID不能证明实例在运行所以必须配合进程检查。# 确认当前环境变量指向的实例 $ env | grep ORACLE_SID ORACLE_SIDUWNMS3 # 查看 Oracle 后台进程是否齐全按实际 SID 过滤 $ ps -ef | grep ora_ | grep UWNMS3 oracle 18100 1 0 Jul14 ? 00:02:13 ora_pmon_UWNMS3 oracle 18102 1 0 Jul14 ? 00:05:41 ora_smon_UWNMS3 oracle 18104 1 0 Jul14 ? 00:12:08 ora_dbw0_UWNMS3 oracle 18106 1 0 Jul14 ? 00:31:22 ora_lgwr_UWNMS3 oracle 18108 1 0 Jul14 ? 00:01:55 ora_ckpt_UWNMS3逻辑说明ps -ef列出所有进程grep ora_过滤 Oracle 后台进程再grep一次 SID 排除其他实例干扰。参数上-ef是 System V 风格的全格式输出能看到启动时间和累计 CPU 时间。如果某个进程的累计 CPU 时间长期为 0 或者进程根本不在列表里说明实例可能处于 nomount 或 mount 状态需要进一步用sqlplus / as sysdba执行select status from v$instance;确认。2.2 多实例环境下怎么批量确认一台主机跑多个实例时逐个env切换效率太低。常见做法是写一个循环把/etc/oratab里的 SID 读出来逐个检查。/etc/oratab是 Oracle 安装时生成的实例注册表格式是SID:ORACLE_HOME:Y/N最后一列表示是否自动启动。#!/bin/bash # 从 /etc/oratab 读取所有实例并检查后台进程 while IFS: read -r sid home autostart; do # 跳过注释行和空行 case $sid in \#*|) continue ;; esac count$(ps -ef | grep ora_.*_${sid} | grep -v grep | wc -l) if [ $count -ge 5 ]; then echo [OK] $sid 后台进程数: $count else echo [WARN] $sid 后台进程数: $count (预期至少 5 个) fi done /etc/oratab逻辑说明IFS:把冒号设为字段分隔符read -r sid home autostart逐行读取三个字段。case语句跳过以#开头的注释行。grep -v grep排除 grep 自身进程。阈值设 5 是因为最小实例至少要有 PMON、SMON、DBW0、LGWR、CKPT 五个进程。这个脚本可以直接放进 crontab 每小时跑一次输出重定向到巡检日志。注意/etc/oratab在 RAC 环境下每个节点都有但内容可能不同巡检时要确认当前节点实际运行的实例列表不能只看文件。3. 文件系统与日志清理空间告警的血泪经验3.1 df 命令在不同 Unix 上的差异文件系统空间检查看起来简单但不同 Unix 的df参数不统一这是实际巡检里最容易翻车的地方。Solaris 上df -h可用AIX 上要用df -g或df -kHP-UX 上则是bdf或df -k。如果脚本里写死了df -h换一台主机就报错。操作系统推荐命令输出单位备注Solarisdf -hGB支持-h人类可读AIXdf -gGB-g以 GB 为单位HP-UXbdfKBbdf是 HP 专有命令Linuxdf -hGB通用巡检时要特别关注三类目录根目录/、$ORACLE_BASE所在的软件目录、归档日志目录示例中是/archivelog。根目录满了会导致系统命令无法执行软件目录满了会影响补丁和升级归档目录满了会直接让数据库挂起。阈值一般设 10%低于这个值就要清理。# 跨平台空间检查优先用 df -h失败则回退到 df -k if ! df -h /dev/null 21; then DF_CMDdf -k else DF_CMDdf -h fi # 检查关键挂载点使用率超过 90% 则告警 $DF_CMD | awk NR1 { gsub(/%/,,$5); if ($50 90) print [ALERT] $6 使用率 $5 % }逻辑说明先探测df -h是否可用不可用则回退到df -k。awk里NR1跳过表头gsub(/%/,,$5)去掉百分号$50强制转数值比较。$6是挂载点。这个写法在 Solaris 和 Linux 上都能跑AIX 上需要把df -h换成df -g。3.2 bdump、cdump、udump 日志清理的边界这三个目录是 Oracle 的跟踪文件目录。bdump放告警日志和后台进程跟踪cdump放核心转储udump放用户进程跟踪。示例里udump下有个uwnms1_ora_18095.trc达到 4.5MBbdump下有core_18095和core_25934两个核心转储文件这些都是空间杀手。清理策略不是无脑rm -rf。alert_SID.log必须保留它是排查问题的第一手资料。core文件确认无用后可以删但删之前最好记录文件名和时间万一后续要追查崩溃原因还有线索。.trc文件按修改时间排序保留最近 7 天的更早的可以清理。# 清理 7 天前的 trc 文件保留 alert 日志和最近的核心转储 BDUMP$ORACLE_BASE/admin/$ORACLE_SID/bdump UDUMP$ORACLE_BASE/admin/$ORACLE_SID/udump # 删除 7 天前的 trc 文件 find $BDUMP $UDUMP -name *.trc -mtime 7 -exec rm -f {} \; # 核心转储文件单独处理先列出再删除 find $BDUMP -name core_* -mtime 7 -print # 确认无误后执行删除 # find $BDUMP -name core_* -mtime 7 -delete逻辑说明-mtime 7表示修改时间超过 7 天-exec rm -f {} \;对每个匹配文件执行删除。核心转储先-print列出人工确认后再换成-delete这是后悔药式的操作习惯。参数上-name *.trc匹配跟踪文件不会误删alert日志。3.3 监听日志的清空技巧监听日志listener.log在$ORACLE_HOME/network/log下示例中已经涨到 272MB。这个文件不能直接rm因为监听进程持有文件句柄删了空间不释放。正确做法是用cp /dev/null清空内容文件句柄保持不变。# 清空监听日志不删除文件本身 cd $ORACLE_HOME/network/log cp /dev/null listener.log # 确认文件大小归零 ls -l listener.log逻辑说明cp /dev/null listener.log把空设备的内容覆盖到日志文件文件 inode 不变监听进程继续写入。sqlnet.log同理。这个操作不需要重启监听风险极低。但要注意清空之前如果正在排查网络问题先把日志备份一份。注意listener.log清空后之前的网络连接记录就没了。如果近期有连接异常先cp listener.log listener.log.bak再清空。4. 备份验证与表空间排查别等恢复时才发现备份是坏的4.1 RMAN 备份有效性怎么快速确认备份检查不能只看备份日志里有没有ERROR还要确认备份集在 RMAN 目录里是AVAILABLE状态。示例中用了rman target / nocatalog加list backup这是最直接的验证方式。nocatalog表示不使用恢复目录直接读控制文件里的备份记录。# 连接 RMAN 并列出备份集 rman target / nocatalog EOF list backup summary; list backup of database; exit; EOF逻辑说明EOF是 here-document把后续命令喂给 rman。list backup summary输出备份概览list backup of database只看数据库备份。输出里重点看Status字段AVAILABLE表示可用EXPIRED表示文件已丢失。如果看到EXPIRED说明备份文件被误删或移动需要立即重新备份。对于 EXP/EXPDP 逻辑备份检查方式不同。exp的日志里搜successfullyexpdp的日志在$ORACLE_BASE/admin/SID/dpdump下搜completed successfully。第三方备份工具则看各自的日志目录这个没有统一标准按工具文档来。4.2 表空间使用率脚本的参数解读表空间检查的核心是算使用率。示例里的 SQL 用dba_data_files算总大小用dba_free_space算剩余空间两者相除得到使用率。这个脚本有个细节dba_free_space里可能没有某些表空间的记录比如全是自动扩展的临时表空间所以用了()外连接。SELECT t.tablespace_name, total, free, ROUND(100 * (1 - (free / total)), 3) || % AS used_pct FROM (SELECT tablespace_name, SUM(bytes) / 1024 / 1024 AS total FROM dba_data_files GROUP BY tablespace_name) t, (SELECT tablespace_name, SUM(bytes) / 1024 / 1024 AS free FROM dba_free_space GROUP BY tablespace_name) f WHERE t.tablespace_name f.tablespace_name() AND t.tablespace_name NOT IN (DRSYS,ORDIM,SPATIAL,USERS,TOOLS,XDB) ORDER BY ROUND(100 * (1 - (free / total)), 3) DESC;逻辑说明内层两个子查询分别算总大小和剩余空间单位是 MB。()是 Oracle 的外连接语法保证即使dba_free_space里没有记录总大小也能显示。NOT IN排除系统表空间这些表空间的使用率波动大巡检时单独看。ORDER BY ... DESC让使用率最高的排在最前面一眼就能看到风险点。参数上SUM(bytes)/1024/1024把字节转成 MB如果数据库很大可以改成/1024/1024/1024转 GB。阈值判断在应用层做比如使用率超过 85% 就告警。4.3 失效索引和数据文件状态检查失效索引不影响查询但影响 DML 性能而且重建索引需要额外空间。示例里的脚本查dba_indexes里status不是VALID的记录以及user_ind_partitions里status UNUSABLE的分区索引。-- 检查失效索引 SELECT index_name, table_name, status FROM dba_indexes WHERE status NOT IN (VALID, N/A); -- 检查失效的分区索引 SELECT index_name, partition_name, tablespace_name FROM user_ind_partitions WHERE status UNUSABLE; -- 检查数据文件状态 SELECT file_name, status, tablespace_name FROM dba_data_files WHERE status ! AVAILABLE;逻辑说明dba_indexes是全局视图user_ind_partitions是当前用户视图两者互补。status ! AVAILABLE查数据文件如果有记录说明文件离线或损坏必须立即处理。重建索引的语句示例里给了ALTER INDEX ... REBUILD TABLESPACE ... ONLINE NOLOGGING PARALLEL 4ONLINE保证重建时不阻塞 DMLNOLOGGING减少 redo 生成PARALLEL 4加速重建。重建完记得NOPARALLEL恢复默认。注意NOLOGGING重建索引期间如果数据库崩溃索引可能损坏需要重新重建。生产环境建议在维护窗口做或者用LOGGING模式。5. 避坑与常见问题巡检脚本翻车的五个真实场景5.1 现象脚本在 AIX 上报df: illegal option -- h原因AIX 的df不支持-h参数只支持-gGB和-kKB。脚本里写死了df -h换平台就挂。解决在脚本开头做平台探测用uname判断操作系统然后设置对应的DF_CMD变量。或者直接用df -k虽然输出是 KB 但兼容性最好后续用awk换算。5.2 现象清理bdump后数据库启动报ORA-00312原因误删了alert_SID.log或者正在使用的.trc文件。Oracle 某些后台进程会持续写跟踪文件删除正在写入的文件会导致进程异常。解决清理前先确认文件修改时间只删 7 天前的。alert日志永远不删用cp /dev/null清空。正在被进程持有的文件用fuser或lsof确认。5.3 现象list backup输出里全是EXPIRED原因备份文件被操作系统层面的清理脚本删了但 RMAN 目录里还有记录。或者备份到磁带后磁带被覆盖RMAN 不知道。解决先crosscheck backup让 RMAN 核对实际文件然后delete expired backup清理失效记录。之后重新做一次全备确认AVAILABLE。5.4 现象表空间使用率脚本查出来是负数原因dba_free_space里某些表空间的剩余空间大于dba_data_files里的总大小通常是因为数据文件自动扩展后dba_data_files没及时更新或者临时表空间混进来了。解决在 SQL 里加AND t.tablespace_name NOT IN (SELECT tablespace_name FROM dba_temp_files)排除临时表空间。或者用dba_tablespace_usage_metrics视图这个视图直接给出使用率不用自己算。5.5 现象CRS 检查命令crs_stat -t报command not found原因crs_stat在 Oracle 10g RAC 里可用但 11g 之后被crsctl stat res -t替代。环境变量$ORA_CRS_HOME没设置也会导致找不到命令。解决先echo $ORA_CRS_HOME确认变量然后cd $ORA_CRS_HOME/bin再执行。11g 及以上用crsctl stat res -t输出格式不同但信息更全。OCR 检查用ocrcheck投票盘用crsctl query css votedisk这些命令在 10g 和 11g 里基本一致。6. 把巡检做成自动化从手动敲命令到 Excel 报表手动巡检最大的问题是漏项和不可追溯。我一般会把前面几章的检查项写成一个 shell 脚本输出结构化文本再用 Python 转成 Excel。这样每天早上一封邮件就能看到所有实例的健康状态。import subprocess import re from openpyxl import Workbook def check_tablespace(sid): 通过 sqlplus 查询表空间使用率 sql SET PAGESIZE 0 FEEDBACK OFF SELECT tablespace_name || | || ROUND(100*(1-(free/total)),2) FROM (SELECT tablespace_name, SUM(bytes)/1024/1024 total FROM dba_data_files GROUP BY tablespace_name) t, (SELECT tablespace_name, SUM(bytes)/1024/1024 free FROM dba_free_space GROUP BY tablespace_name) f WHERE t.tablespace_name f.tablespace_name(); # 通过环境变量切换 SID 后执行 env {ORACLE_SID: sid, PATH: /usr/bin:/bin} result subprocess.run( [sqlplus, -S, / as sysdba], inputsql, capture_outputTrue, textTrue, envenv ) rows [] for line in result.stdout.strip().split(\n): if | in line: name, pct line.split(|) rows.append((name.strip(), float(pct))) return rows # 生成 Excel 报表 wb Workbook() ws wb.active ws.title 表空间巡检 ws.append([实例, 表空间, 使用率(%), 状态]) for sid in [UWNMS1, UWNMS3]: for name, pct in check_tablespace(sid): status 告警 if pct 85 else 正常 ws.append([sid, name, pct, status]) wb.save(/tmp/oracle_inspect.xlsx)逻辑说明subprocess.run执行sqlplus -S-S是静默模式去掉 banner 和提示符。inputsql把 SQL 通过标准输入传给 sqlplus。env参数覆盖环境变量实现不切换 shell 就查不同实例。openpyxl写 Excelws.append逐行追加。状态列用 85% 做阈值超过就标告警。这个脚本可以扩展把文件系统检查、备份检查、失效索引检查都加进去每个检查项一个 sheet。跑完用crontab定时执行输出文件放到共享目录运维早上直接看报表。注意sqlplus的路径要写全crontab 的环境变量和登录 shell 不同ORACLE_HOME和PATH都要显式设置否则会报sqlplus: not found。从那以后我每次写巡检脚本都强制先在测试环境跑一遍确认df参数、sqlplus路径、ORACLE_SID切换都没问题再上生产。这套方案里的命令和脚本都是经过实际环境验证的照着改改就能用。希望帮到你。本文还有配套的精品资源点击获取
返回列表