简介这是一份面向Oracle数据库运维与DBA人员的案例型PPT课件聚焦RAC集群环境下的故障分析与处置流程。内容以真实错误日志为主线逐一剖析IPC Send timeout、LMS/LMD锁管理进程通信异常、实例成员资格不一致、脑裂驱逐以及ORA-29740报错等典型现象解释IPC超时通常源于网络延迟、丢包或进程阻塞LMS/LMD分别负责处理与维护锁信息脑裂机制会驱逐异常实例以保障数据一致性同时也结合netstat确认网络丢包、资源瓶颈与Oracle已知BUG等诱因并给出从日志分析、网络检查、资源监控到补丁排查的系统排错思路对定位类似生产事故很有参考价值。压缩包共有1个文件为pptx演示文稿约1.83MB适合具有一定集群基础、希望提升Oracle RAC故障排查能力的运维人员学习参考。该资源已有133人学习下载可直接用于团队技术分享或个人复盘。1. Oracle 数据库运维案例从翻车现场到标准动作凌晨一点开发打电话说订单库查询卡死你冲到工位查v$session看到一片buffer busy waits。翻出同事留下的 Oracle数据库运维案例介绍.pptx里面有十年前的同类故障记录却只有截图和命令没写先查什么、参数为什么这么改。这类运维案例的价值从来不在屏幕截图而在把一次救火过程拆成可复用的标准动作报错是什么、先查哪张视图、参数改多少、观察多久。这篇笔记就按这个思路把 Oracle 数据库运维案例背后最常见的打法讲清楚先分可用性、性能、安全三层再落到 DG 同步搭建、AWR 定位、故障排查和巡检脚本。适合刚接手 Oracle 库的运维工程师也适合准备从 MySQL 转过来的 DBA。2. Oracle 数据库运维案例先分清可用性、性能、安全三层2.1 可用性层同步、备份、恢复是一条保命线我翻过的运维案例文件夹里占比最大的永远是数据库起不来、主备不同步、数据文件报错、磁盘打满。这一层只回答一个问题库真垮了多久能站起来数据丢多少。Oracle 在这一层有三个标配归档模式、DG 数据同步、RMAN 备份。归档是一切的基础不开归档就没有完整的恢复能力DG 是数据库层最常用的同步软件方案既能做主备容灾也能把只读查询分到备库RMAN 则是备份和恢复的主通道。很多案例把这三点分开记实际运维里它们是一条线归档产生连续性DG 靠归档和日志同步RMAN 靠归档做时间点恢复。看这类案例不要只抄命令要带着顺序看。我一般会先确认这个库是单实例还是 RAC有没有备库备份策略是什么。单实例和 RAC 的排查路径完全不同DG 环境里出问题还要先分清主备角色。案例里只要出现alter database archivelog就要追问一句这条命令执行前库是 mount 还是 open 状态。很多新人抄了命令却不知道要先shutdown immediate再startup mount结果在 open 状态直接报 ORA-01126这就是案例没有写清“边界条件”的典型后果。一份能复用的案例文档我要求至少记五要素环境版本、初始症状、定位命令、变更命令、验证结果。环境版本包括操作系统、Oracle 版本、单实例还是 RAC、是否 DG初始症状要写原话报错而不是人肉翻译后的描述定位命令要写“执行后看哪一列”变更命令要写“改了之后是否需要重启”验证结果要写“观察多久、看什么指标”。没有这五要素只能算截图收藏夹收藏了一百个遇到问题还是从零开始。2.2 性能层AWR、等待事件和 SQL 定位一年里真正让运维睡不着的不是数据库挂掉而是库没挂、业务天天被投诉。这类案例看起来玄学实际路径非常固定先抓 AWR 快照看 Top 10 事件再定位到 SQL 和执行计划最后评估是加索引、改参数还是改应用。Oracle 性能文档里出现频率最高的词是“等待事件”它回答的是“数据库当前在等什么资源”。等 CPU、等数据文件读、等日志写、等行锁原因完全不同处理手段也完全不同。我见过不少案例把用户等待时间和 DB 时间混在一起讲这是第一个坑。看 AWR 先看DB Time / Elapsed比值大于 1 说明数据库确实忙小于 1 说明周期里有大量空闲问题可能不在数据库段。还有开发拿着 Dragonwell 和 Oracle JDK 的对比来问数据库是不是太慢这种属于应用托管的 JDK 与数据库实例被混为一谈。我一般会先让时间说话同一套 SQL 在 sqlplus 里跑得飞快在应用里慢问题大概率不在数据库先查连接池和网络往返再进 AWR。性能案例里最容易写进 PPT 的其实是函数和存储过程。比如一个普通函数没加确定性导致每行数据都重复执行一次一个存储过程逐行 update百万行数据跑半小时回滚段还差点被撑爆。这类代码级问题不解决调大 SGA 也只是花钱买时间。顺便说一句PPT 里常有一页“oracle 中 dual 最多存多大”这类单行问题记下来当知识点可以但对生产影响很小真正要盯的是等待事件和执行计划。dual 是单行单列表21c 之后某些版本还能自定义列但它从来不是性能瓶颈。2.3 安全合规层等保命令不是临时抱佛脚第三层是安全和合规。每年等保测评前DBA 都要花几天改数据库基线密码策略、登录失败处理、审计策略、最小权限。Oracle 等保命令在网上流传很广但真正要做的是先看清基线要求再改参数。默认的 profile 允许无限次失败登录要求改成连续 5 次失败锁定默认audit_trail可能是 NONE要改成 DB 或 OS默认远程访问限制不严要配合tcp.validnode_checking做 IP 白名单。这些改完有的动态生效有的要重启必须逐条记录。等保这块最容易翻车的不是命令本身而是“改完没有验证”。比如alter profile default limit password_life_time 90之后只对之后改密用户生效存量用户还是原来的过期时间要结合dba_users里的expiry_date一起检查。审计打开之前还要想清楚磁盘够不够放AUD$表的数据否则审计刚开三天SYSTEM 表空间就被写满数据库直接挂起。案例文档里如果只写了打开审计没写清理策略这类内容宁可先不上线。层次核心问题典型案例常用手段可用性库能不能撑住、数据丢不丢DG 断同步、归档满、dbf 损坏RMAN、DG、归档策略性能业务慢、会话堆积AWR Top 事件、分页慢、存储过程逐行AWR、执行计划、索引、SQL改写安全等保测评不通过、权限失控口令策略、审计未开、远程访问过宽profile、audit、IP 限制拿到一份运维案例先判断它属于哪一层再决定动作。这步 30 秒能完成能省下后面两小时的弯路。现在很多问题的表象会跨层比如归档目录写满导致业务报错表面是空间问题根因可能是备库断同步那就同时在可用性层处理而不是光删归档。3. Oracle 19c 单实例搭 DG最小同步环境这样落地3.1 DG 的最小原理与四个前提DG 是 Oracle 自带的数据同步工具跟外部数据库同步软件比最大的优势是深度集成、支持角色切换、不需要额外部署中间件。物理备库的原理一句话讲清主库的日志传输服务把 redo 传到备库备库的 MRP 进程把 redo 应用到自己的数据文件上。同步方式分为 SYNC 和 ASYNC保护模式分为最大保护、最大可用、最大性能。单实例对单实例是最常见的起步组合也是后面扩展 RAC 的基础所以我建议新手都从 19c 单实例搭 DG 练手。动手前先确认四个前提主备都是 19c 同版本操作系统架构一致主备都能通过静态监听互连主库已开归档系统时间基本一致最好配了 NTP。静态监听是关键很多 DG 搭不通都是监听里没有 SID 列表tnsping通但服务名解析不对。备库可以先用一套全新的空环境不需要提前装数据库软件以外的任何东西19c 的 active duplicate 会自己把数据文件复制过去。3.2 主库开启归档并设置 DG 参数下面这组操作在主库执行注意每一条的意图。-- 1. 重启到 mount 状态开启归档 shutdown immediate; startup mount; alter database archivelog; alter database force logging; alter database open; -- 2. 设置主库 DG 相关参数 alter system set db_unique_nameorcl scopespfile; alter system set log_archive_configdg_config(orcl,orclstd) scopespfile; alter system set log_archive_dest_1location/u01/app/oracle/arch VALID_FOR(ALL_LOGFILES,ALL_ROLES) db_unique_nameorcl scopespfile; alter system set log_archive_dest_2serviceorclstd LGWR ASYNC VALID_FOR(ONLINE_LOGFILES,PRIMARY_ROLE) db_unique_nameorclstd scopespfile; alter system set log_archive_dest_state_2enable scopespfile; alter system set log_archive_format%t_%s_%r.arc scopespfile; -- 3. 让 spfile 参数生效 shutdown immediate; startup;第一组命令里shutdown immediate是干净关闭事务startup mount后才能修改归档模式。force logging很关键它保证即使应用里写了 nologging所有数据块操作也会记录日志否则备库很可能在某次操作后与主库不一致。第二组命令里db_unique_name决定了这个库在 DG 配置里的身份log_archive_config用dg_config列了主备两个名字log_archive_dest_2里LGWR ASYNC表示日志写进程直接传输、备库异步接收主库提交不等待备库确认这是保护模式和性能的平衡点VALID_FOR(ONLINE_LOGFILES,PRIMARY_ROLE)表示只有在线日志、只有主库角色时才写往这个目标。3.3 备库参数与 Active Duplicate备库端先启动到 nomount再用 RMAN 的duplicate from active database在线复制。这是 19c 最常见的做法不需要先做全备再传原文备库直接从主库拉原件。# 备库执行启动到 nomount export ORACLE_SIDorclstd sqlplus / as sysdba EOF startup nomount; EOF # 主库终端执行用 RMAN 复制 rman target sys/sys_passwordorcl auxiliary sys/sys_passwordorclstd RMAN duplicate target database for standby from active database nofilenamecheck;no filenamecheck的前提是主备库目录结构完全一致。如果备库的数据文件路径和主库不同就不能带这个参数而是要在备库 pfile 里配db_file_name_convert和log_file_name_convert指定路径映射关系。nofilenamecheck看似省事但生产上主备目录不一致很常见硬用会直接报 ORA-19611所以这里要按实际目录决定。复制完成后备库会自动生成控制文件和数据文件但还需要手动把备库切到 managed recovery 状态。alter database recover managed standby database using current logfile disconnect from session;using current logfile表示备库使用传输过来的在线日志做实例恢复这是 19c 默认的推荐方式。disconnect from session让恢复进程在后台运行不会因为 SQL*Plus 断开而停止。执行后可以用select process,status from v$managed_standby;看 MRP0 是否变成 APPLYING_LOG。3.4 验证同步和角色切换同步有没有跟上不要看感觉要看两个数备库应用的日志序列号以及它落后主库多少。-- 主库强制切一次日志产生新的 redo alter system switch logfile; -- 备库查询 select database_role, db_unique_name, open_mode from v$database; select sequence#, applied from v$archived_log where sequence# (select max(sequence#)-5 from v$archived_log) order by sequence# desc; select * from v$dataguard_stats;v$archived_log里appliedYES表示这条日志已经在备库应用完成。v$dataguard_stats里主要看两个值transport lag和apply lag正常应该都是00 00:00:00带号且数字变大就说明有延迟。生产上建议把备库的编译检查也纳入巡检比如在备库执行select count(*) from 核心表如果备库处于 mount 状态这一步要先建立 snapshot standby 或打开只读模式。日常切换我建议用 DG Broker手工 switchover 命令容易在忘记清理db_unique_name时出问题。用 broker 的思路是先建配置再启用再验证不要跳步。-- 调用 dgmgrl dgmgrl sys/sys_passwordorcl DGMGRL create configuration cfg as primary database is orcl connect identifier is orcl; DGMGRL add database orclstd as connect identifier is orclstd maintained as physical; DGMGRL enable configuration; DGMGRL show configuration;connect identifier必须是监听里能解析的服务名不是任意起的别名。enable configuration之后broker 会接管日志传输和恢复的启动手工在 SQL*Plus 里停恢复再启动broker 反而会误判状态。3.5 日常备份脚本RMAN 与归档清理DG 再稳RMAN 也不能省备库不代表能恢复到任意时间点所以日常备份脚本是案例里的标准动作。#!/bin/bash # 每日凌晨 1 点执行归档保留 3 天 export ORACLE_HOME/u01/app/oracle/product/19c/dbhome_1 export ORACLE_SIDorcl export PATH$ORACLE_HOME/bin:$PATH rman target / EOF crosscheck archivelog all; delete noprompt archivelog until time sysdate - 3; backup database format /u01/backup/db_%U.bkp plus archivelog; backup current controlfile format /u01/backup/ctl_%U.bkp; delete noprompt obsolete; EOFcrosscheck archivelog all是为了让 RMAN 的元数据和磁盘上真实文件对齐否则以后delete obsolete可能删不掉已经消失的文件记录。until time sysdate - 3是清理三天前的归档注意这是截止时间不是保留三天写反会把当天的归档全删掉。plus archivelog保证备份期间切出来的归档也包含进去备份集才是自洽的。delete obsolete按保留策略清理过期备份默认保留策略是一份冗余如果配了redundancy 2会多保留一份。脚本跑完不等于恢复没问题我习惯再加一步验证rman target / RMAN restore database validate; RMAN validate backupset;restore database validate会把整个备份集读一遍真实验证有没有坏块、缺文件但不落盘。所有案例里最常被省略的就是恢复验证备份跑了三年真到恢复才发现缺文件这种事故我不止见过一次。4. 从 AWR 报表到 SQL 调优性能类案例的定位路径4.1 生成 AWR 报表的准确姿势性能案例的第一步永远是拿报告不是拍脑袋改参数。先确认快照范围再生成 HTML 报告。-- 列出最近 7 天的快照 select snap_id, begin_interval_time, end_interval_time from dba_hist_snapshot where begin_interval_time sysdate - 7 order by snap_id; -- 用指定快照区间生成 HTML 报告 select dbms_workload_repository.awr_report_html( l_dbid (select dbid from v$database), l_inst_num 1, l_bid 1220, l_eid 1230, l_rpt_options 8) report_html from dual;l_bid和l_eid是开始和结束快照 ID一般选业务高峰时间段不要选跨了一整天的区段否则 Top 事件会被平均掉。l_rpt_options 8表示包含详细的 SQL 统计信息关键是能直接看到 SQL 的执行次数、平均耗时、CPU 和物理读。如果现场没有图形界面也可以把awr_report_html换成awr_report_text文本报告在终端里更好翻。拿到报告先看两块顶部DB Time / Elapsed的比例以及Top 10 Foreground Wait Events。比例明显大于 1 说明数据库确实在忙小于或接近 1 说明当前区间数据库有空闲慢的根源在别处。Top 事件列表可以看作“数据库自己告诉你它卡在哪”。这一步不要跳过直接往下翻 SQL 列表经常会被一两条偶发 SQL 带偏。4.2 三个高频等待事件看一眼就知道方向AWR 里每天出现最多的是下面这三个每个对应一套固定排查动作。等待事件常见原因第一步动作db file sequential read单块读慢多半是索引访问、表访问路径不合理到 SQL 列表找物理读高的语句看执行计划是否走索引索引是否失效log file sync提交慢redo 写入跟不上查 redo log 大小和磁盘 fsync 延迟必要时增大日志组、换高性能盘enq: TX - row lock contention行锁等待应用事务没提交查 v$locked_object、v$session 关联出阻塞会话让业务确认事务是否已经挂起db file sequential read最容易误判成磁盘坏道。它本质是一种 I/O 等待类型单块读慢可能是因为 buffer cache 过小、表和索引被频繁热切换也可能是批量任务把 I/O 带宽占满。所以看到它先看平均等待时间再关联 SQL不要急着加内存。log file sync则和磁盘直接相关redo log 文件所在的磁盘如果和归档目录混在一起很容易出现写放大。实践里先看v$log里日志成员大小太小就加组加大小太大反而会延长切换周期需要反复观察。4.3 分页查询带来的慢 SQLOracle 分页是老生常谈但案例里十有八九是深分页翻车。深分页的意思是用户要第 19990 到 20000 页的数据页数越大越慢。低效写法是先把前 N 万行全部取出再丢弃。-- 低效先取 20 万行再丢 199990 行 select t.*, rownum rn from ( select * from orders order by created_time desc ) t where rownum 200000 and rn 199990;这段 SQL 的执行为什么慢内层排序要处理全表数据外层 rownum 限制了 20 万行实际返回却只有 10 行数据库把绝大多数时间浪费在拿和丢上。改法是让数据库只处理那一页前后的数据而不是覆盖整张表。-- 高效先定位上一页最后一条的位置再往后取 10 条 select * from orders where created_time ( select created_time from ( select created_time from orders order by created_time desc ) where rownum 199990 ) order by created_time desc fetch first 10 rows only;子查询先找到上一页那行的 created_time外层只用大于该值的 10 行。前提是 created_time 有索引且值足够区分否则要用组合排序条件。19c 里fetch first 10 rows only是标准写法12c 之前的版本还是写rownum 10。深分页优化后如果页数非常深还可以用 keyset pagination 记录上一页最后一行 id彻底避免扫大偏移量。案例文档里应该同时记录两种写法并标注“第几页开始切换策略”。4.4 存储过程里的逐行处理和函数坑存储过程性能案例最常见的是逐行 update。业务逻辑用游标循环处理百万级数据每行 update 一次SQL 引擎上下文切换和 undo 生成量都爆表。反例-- 反例游标循环逐行更新 declare v_count pls_integer : 0; begin for rec in (select id, status from t_order where status 0) loop update t_order set status 1 where id rec.id; v_count : v_count 1; if mod(v_count, 1000) 0 then commit; end if; end loop; commit; end; /这段代码在数据量小的时候没感觉到几十万行就开始慢。每条 update 都是一次上下文切换每 1000 行一次 commit 虽然避免了回滚段爆掉但日志同步次数并没有少。改成集合操作-- 正例一条 update 解决 update t_order set status 1 where status 0;如果业务要求逐条做校验推荐先批量把数据载入临时表再一次性 update 或 merge。案例里记录这种对比比记录存储过程语法更值钱因为语法翻手册就有性能规律是从故障里摸出来的。函数坑也常见。比如查询条件里把索引列套进函数索引直接失效。-- 反例trunc 包住索引列走不了索引 select * from epay_trans where trunc(create_time) date2024-06-01; -- 正例改成范围条件 select * from epay_trans where create_time date2024-06-01 and create_time date2024-06-02;注意这里date2024-06-02是当天零点和第二天零点相差一秒上界使用小于号刚好覆盖 6 月 1 日全天。如果业务上 create_time 带时分秒写成 date2024-06-01 23:59:59会漏掉最后一秒的数据所以统一用半开区间最安全。案例文档里应该把这个写法作为标准模板固定下来。5. 运维案例里的高频故障五条避坑与排错记录案例看多了会发现故障其实就那几类。下面五条是我自己踩过、也看同事踩过的记录每条按现象到解决展开。5.1 dbf 文件损坏别急着找第三方工具现象alert 日志报 ORA-01115 / ORA-01116说文件块读错误或文件不可读数据库可能还在运行但查询相关表直接报错。有人拿 SQLite 的 dbx 工具去打开 dbf 文件方向就错了Oracle 数据文件不是随便用外部工具解析的。原因磁盘坏道、掉电时数据块未完全落盘、文件被误删。先确认是数据文件还是临时文件临时文件损坏可以重建数据文件损坏需要备份恢复。解决先查文件号定位再决定恢复路径。select file#, name, status from v$datafile; -- 如果 datafile 7 损坏 rman target / RMAN restore datafile 7; RMAN recover datafile 7;如果是临时文件损坏直接删了重建不需要备份alter tablespace temp add tempfile /u01/app/oracle/oradata/temp02.dbf size 2g; alter database tempfile /u01/app/oracle/oradata/temp01.dbf drop including datafiles;数据文件损坏最怕没有备份所以第 3 章的日常备份脚本和恢复验证是这类事故的后悔药。这里多说一句数据库层面确定是文件坏之后先别急着恢复把报警磁盘的坏道情况也记录一下否则恢复完文件又坏一次。5.2 包状态被丢弃调用直接报 ORA-04068现象生产上调用存储过程报 ORA-04068原有包不可用查询dba_objects发现状态变成 INVALID。这也是热词“oracle 为什么会出现包状态被丢弃”对应的场景。原因依赖对象被 DDL 改动或者升级脚本只改了表结构没有重新编译依赖它的包。包状态不是真的被“丢弃”而是依赖链失效。解决先查出所有失效对象再按需编译。select owner, object_name, object_type, status from dba_objects where status VALID and owner APP and object_type in (PACKAGE,PACKAGE BODY,PROCEDURE,FUNCTION,VIEW); -- 对失效的包逐个编译 alter package app.pkg_order compile body;也可以写匿名块循环编译但不要无脑对整个 schema 执行dbms_utility.compile_schema。这个命令会把所有对象重新编译生产环境里可能引发大量锁和性能抖动。我一般只筛出失效对象编译前看一眼依赖关系特别是包体引用了别的 schema 的包时要先编译被引用的那层。5.3 12c 删除不干净重装时处处碰壁现象用 dbca 删除实例后想重装dbca 列表里还显示旧实例安装到一半提示目录已存在或监听服务被占用。热词里的“12c 删除不干净 oracle”指的就是这类残留。原因deinstall 只删了数据库软件注册信息/u01/app/oracle下的 oradata、diag 目录还在/etc/oratab里的记录没有清理监听配置文件里服务项也残留。解决按顺序清理先停库和监听再删目录和配置文件。lsnrctl stop sqlplus / as sysdba EOF shutdown abort; EOF rm -rf /u01/app/oracle/oradata/ORCL rm -rf /u01/app/oracle/diag rm -f /etc/oratab # 如果有 dbhome 里的 old install 残留也要清理注意这是在确认不需要任何数据恢复的前提下执行。生产环境删除实例前先把最后一个全备和归档复制到异地再做清理。数据库的卸载本质上跟删除生产数据一个等级不能图省事跳过备份。5.4 归档目录写满业务新事务报错现象应用突然报 ORA-00257数据库能查但新事务提交不了。查v$recovery_area_usage或v$recovery_file_dest发现空间已满。这个案例在 DG 环境里尤其常见因为日志传输暂停时归档会在主库堆积。原因归档清理策略没生效或者备库断开导致主库日志无法删除。备库断开的信号是v$archive_dest里目标状态变成 ERROR主库的归档会越积越多。解决先确认备库状态有没有追上再决定删多少。select dest_id, status, error from v$archive_dest; -- 备库如果正常再清理过期归档 rman target / EOF crosscheck archivelog all; delete noprompt archivelog until time sysdate - 2; EOF顺序很重要先确认备库已经应用完要删的归档再在主库清理。否则主库删了备库再申请这段日志就永久缺档只能重建备库。生产上我给备库单独留了快照备份就是为了在断同步太久时能快速重搭。5.5 等保命令基线检查到底改在哪现象测评报告列出口令策略、失败锁定、审计未开启等不符合项。等保命令不是网上抄几条就完事要理解改动的位置。原因默认 profile 允许无限次失败登录audit_trail默认是 NONE远程访问也没有限制。这些都是默认配置与测评要求的差距。解决先按测评要求列基线再改 profile 和审计参数。-- 密码策略与失败锁定 alter profile default limit failed_login_attempts 5 password_lock_time 1 password_life_time 90 password_reuse_time 365; -- 打开审计DB 级别 alter system set audit_traildb, extended scopespfile; -- 12c 之后常用统一审计 alter system set unified_audit_sga_queue_size1g scopespfile;注意audit_trail改成 DB 后要重启库而且AUD$表会长得很快。案例文档里要同步记录清理策略定期对AUD$做分区归档或者开启统一审计后配置定期导出。只开审计不建清理任务的案例基本都会在三个月后以“SYSTEM 表空间爆满”收场。6. 把案例沉淀成巡检手册与验证脚本案例看了再多落地要靠巡检。我现在每接手一个库第一周就写一个能一分钟跑完的巡检脚本。脚本不追求面面俱到先把五件事查清楚实例状态、备份是否成功、归档目录余量、DG 延迟、表空间使用率。#!/bin/bash # 每日巡检脚本输出固定格式便于比较 export ORACLE_HOME/u01/app/oracle/product/19c/dbhome_1 export ORACLE_SIDorcl export PATH$ORACLE_HOME/bin:$PATH sqlplus -s / as sysdba EOF set linesize 200 pagesize 100 select instance_name, status, database_role from v\$instance, v\$database; select name, round(percent_space_used, 1) used_pct from v\$recovery_area_usage; select tablespace_name, round(used_percent, 1) used_pct from dba_tablespace_usage_metrics where used_percent 85; EOF rman target / EOF list backup summary; EOF这里v\$instance里的$在 bash 的 heredoc 里必须转义否则会被 shell 当成变量吃掉。dba_tablespace_usage_metrics是 19c 里查表空间使用率最直接的方式不再需要手写dba_data_files和dba_free_space的 join。输出里如果出现任何一行status不是 OPEN、used_pct大于 85就说明当天要处置。脚本跑通只是第一步还要把输出存成带日期的文件第二天用 diff 比较变化率否则相当于白跑。我自己踩过的最后一个坑巡检脚本里塞了太多指标导致每天的输出超过一百行反而没人看。后来我把脚本精简成只看“异常行”正常状态不输出这样每天早上扫一眼日志文件有没有新内容就够了。案例 PPT 里的命令会过期这套脚本不会它会跟着库一起成长。希望帮到你。本文还有配套的精品资源点击获取