ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Oracle数据库自动化巡检:Python脚本生成Excel健康报告

Oracle数据库自动化巡检:Python脚本生成Excel健康报告 简介本资源是一套面向Oracle数据库运维工程师与DBA的实用巡检工具包聚焦数据库健康检查、性能优化与风险防控等核心运维场景解决日常巡检中脚本缺失、操作无据、结果难解读等痛点。压缩包共2个文件109KB含关键SQL巡检脚本Oracle_DB_Check.sql——用于自动采集性能指标、空间使用、安全配置、备份状态等9类关键数据以及配套的《数据库巡检脚本操作手册.docx》详细说明脚本执行步骤、输出字段释义、异常判断逻辑与典型问题处置建议。资源内容覆盖SQL执行计划分析、SGA/PGA参数评估、索引碎片检测、日志告警审查等实操要点结构清晰、即拿即用。目前已有333人学习下载适合初入Oracle运维岗位的技术人员快速建立标准化巡检能力也便于资深DBA复用脚本框架并扩展定制化检查项。1. 为什么凌晨三点还在改巡检脚本——一个 Oracle DBA 的血泪经验把「人工翻表查状态」变成「定时自动吐 Excel 报告」你有没有经历过凌晨两点收到告警登录数据库一看归档日志满了、表空间快爆了、监听器挂了、AWR 快照没生成……而你翻着 SQL*Plus 一条条执行SELECT * FROM V$INSTANCE;SELECT TABLESPACE_NAME, USED_PERCENT FROM DBA_TABLESPACE_USAGE_METRICS;SELECT STATUS FROM V$LISTENER_NETWORK;——手抖、眼花、漏项、记错命令。这不是运维是人肉 OCR。真正的 Oracle 巡检不是「查几个视图」而是建立一套可复用、可验证、可回溯、可交接的自动化基线检查体系。本篇讲的就是如何用一个压缩包数据库巡检脚本及操作手册.zip落地这件事它不是玩具脚本而是我在 3 家金融、2 家制造企业真实部署过的最小可行方案——含 Python 脚本非 PL/SQL、Oracle 连接池管理、多实例并发采集、Excel 多 Sheet 输出含趋势图嵌入、异常高亮、日志分级归档、以及一份能直接打印给新同事看懂的操作手册。适合 DBA、运维工程师、甚至刚转岗的开发——只要你需要每天确认 Oracle 实例是否「活着、健康、可控」而不是靠直觉或运气。2. 从零跑通用 Python 脚本连接 Oracle 并导出首份 Excel 巡检报告巡检的本质是「把数据库的健康信号翻译成人话」。而 Python 是目前最稳妥的翻译器它不依赖 Oracle Client 图形界面能跨 Linux/Windows 运行自带丰富报表能力且生态成熟cx_Oracle / oracledb pandas openpyxl。本方案采用oracledbOracle 官方推荐的轻量级驱动替代已弃用的 cx_Oracle避免 client 安装和环境变量污染问题。2.1 环境准备三步完成最小依赖安装Linux/Windows 通用提示不要用pip install cx_OracleOracle 官方已在 2023 年 10 月正式弃用该包新项目必须用oracledb。它纯 Python 实现无需 Oracle Instant Client大幅降低部署复杂度。# 创建独立虚拟环境强烈建议 python -m venv ora_check_env source ora_check_env/bin/activate # Linux/macOS # ora_check_env\Scripts\activate.bat # Windows # 安装核心依赖仅 3 个包无冗余 pip install oracledb pandas openpyxloracledbOracle 官方维护的 Python 驱动支持 Oracle 11g–23c兼容 Thin 模式无需本地 client连接字符串写法与 cx_Oracle 兼容。pandas用于结构化数据清洗与聚合比如把V$SESSION中的STATUS字段统计成「ACTIVE: 42, INACTIVE: 187」。openpyxl写 Excel 的事实标准支持多 sheet、样式、图表嵌入后续章节会用到。2.2 配置文件设计把密码、IP、端口、SID 全部抽离拒绝硬编码脚本不能把数据库密码写死在.py文件里——这是安全红线。我们采用config.ini分离配置支持多实例并行巡检# config.ini [ORACLE_INSTANCES] # 格式实例名 host:port:sid:username:password prod_db 192.168.10.10:1521:ORCL:monitor_user:Kx8#mQ2!pL test_db 10.20.30.40:1521:TESTDB:monitor_user:Z9$nR4vTf dev_db 127.0.0.1:1521:DEV:monitor_user:DevPass123 [REPORT_OPTIONS] output_dir ./reports excel_template ./templates/empty_report.xlsx max_workers 3 # 并发采集实例数避免单点阻塞monitor_user必须是只读账号权限严格限定见第 4 章授权脚本密码中含特殊字符如#,!,时configparser默认会误解析为注释——解决方案是用双引号包裹整个密码字段monitor_user:Kx8#mQ2!pL否则脚本会静默失败。2.3 核心巡检逻辑5 类必查指标 1 个兜底 SQL 执行器脚本不是堆 SQL而是按「稳定性 → 容量 → 性能 → 安全 → 可维护性」分层检查。每个检查项返回结构化字典供后续写入 Excel# check_core.py import oracledb import pandas as pd def check_instance_status(conn): 检查实例运行状态必须第一项失败则跳过后续 sql SELECT INSTANCE_NAME, STATUS, DATABASE_STATUS, ACTIVE_STATE FROM V$INSTANCE df pd.read_sql(sql, conn) return { section: 实例状态, data: df, pass: df.iloc[0][STATUS] OPEN and df.iloc[0][DATABASE_STATUS] ONLINE } def check_tablespace_usage(conn): 表空间使用率含自动预警 sql SELECT TABLESPACE_NAME, ROUND(USED_PERCENT, 2) AS USED_PERCENT, CASE WHEN USED_PERCENT 85 THEN ⚠️ 超阈值 ELSE ✅ 正常 END AS STATUS FROM DBA_TABLESPACE_USAGE_METRICS WHERE TABLESPACE_NAME NOT IN (SYSTEM, SYSAUX) -- 排除系统表空间干扰 ORDER BY USED_PERCENT DESC df pd.read_sql(sql, conn) return { section: 表空间使用率, data: df, pass: len(df[df[USED_PERCENT] 85]) 0 } # 更多检查函数check_listener_status(), check_archive_log(), check_long_running_sql()...V$INSTANCE是所有检查的起点若它查不到说明实例根本没起来后续全跳过DBA_TABLESPACE_USAGE_METRICS比传统DBA_TABLESPACESDBA_DATA_FILES计算更准Oracle 11g 内置监控视图所有 SQL 显式加WHERE过滤无关数据如排除 SYSTEM 表空间避免大数据量拖慢脚本。2.4 生成 Excel 报告多 Sheet 自动列宽 异常红标 时间戳水印输出不是简单df.to_excel()而是精细化控制格式让报告开箱即用# report_generator.py from openpyxl import load_workbook from openpyxl.styles import Font, PatternFill, Alignment from openpyxl.utils import get_column_letter def write_to_excel(check_results, output_path): wb load_workbook(./templates/empty_report.xlsx) # 预置带样式的空模板 ws_summary wb[Summary] # 写入汇总页各检查项 PASS/FAIL 状态 for i, r in enumerate(check_results, 2): ws_summary[fA{i}] r[section] ws_summary[fB{i}] ✅ PASS if r[pass] else ❌ FAIL ws_summary[fB{i}].font Font(color007E33 if r[pass] else FF0000) # 为每个检查项创建独立 Sheet for result in check_results: ws wb.create_sheet(titleresult[section][:31]) # Excel sheet 名限 31 字符 df result[data] # 写入表头 for j, col in enumerate(df.columns, 1): cell ws.cell(row1, columnj, valuecol) cell.font Font(boldTrue) cell.fill PatternFill(solid, fgColorDDEBF7) # 写入数据 for i, row in enumerate(df.values, 2): for j, val in enumerate(row, 1): cell ws.cell(rowi, columnj, valueval) # 对含 ⚠️ 的单元格标红 if isinstance(val, str) and ⚠️ in val: cell.font Font(colorFF0000, boldTrue) # 自动列宽 for col in ws.columns: max_length 0 column col[0].column_letter for cell in col: try: if len(str(cell.value)) max_length: max_length len(str(cell.value)) except: pass adjusted_width min(max_length 2, 50) # 限制最大宽度 ws.column_dimensions[column].width adjusted_width # 添加时间戳水印 ws_summary[D1] f生成时间{pd.Timestamp.now().strftime(%Y-%m-%d %H:%M:%S)} wb.save(output_path)使用预置empty_report.xlsx模板含 Summary 页、固定字体、配色避免每次生成都重设样式Sheet 名截断至 31 字符——Excel 严格限制超长会报错ValueError: Sheet name cannot exceed 31 characters⚠️符号触发红色字体比单纯文字更醒目一线人员扫一眼就能定位风险。3. 权限与安全给巡检账号最小必要权限拒绝 DBA 角色滥用巡检账号不是 DBA它只需要「看」不需要「改」。给monitor_user赋予 DBA 角色是典型的安全反模式——一旦密码泄露等于交出整库控制权。我们必须用最小权限原则精确授予每个SELECT所需的视图访问权。3.1 创建只读监控用户含密码策略与资源限制-- 在 SYS 或 SYSTEM 下执行 CREATE USER monitor_user IDENTIFIED BY Kx8#mQ2!pL DEFAULT TABLESPACE users TEMPORARY TABLESPACE temp QUOTA 0 ON users; -- 禁止创建对象 -- 密码策略90天过期错误5次锁定 ALTER USER monitor_user PASSWORD EXPIRE; ALTER USER monitor_user ACCOUNT LOCK; ALTER USER monitor_user PROFILE DEFAULT PASSWORD_LOCK_TIME UNLIMITED PASSWORD_REUSE_TIME 90 PASSWORD_GRACE_TIME 7; -- 资源限制防止恶意长查询耗尽 CPU CREATE PROFILE monitor_profile LIMIT CPU_PER_SESSION UNLIMITED CPU_PER_CALL 3000 -- 3秒CPU时间上限 CONNECT_TIME 30 -- 连接最长30分钟 IDLE_TIME 10 -- 空闲10分钟断开 LOGICAL_READS_PER_SESSION 1000000; ALTER USER monitor_user PROFILE monitor_profile;QUOTA 0 ON users禁止该用户在任何表空间建表/索引彻底杜绝写操作可能CPU_PER_CALL 3000单位是「百分之一秒」即单条 SQL 最多消耗 30 秒 CPU防住SELECT * FROM BIG_TABLE类暴力扫描PASSWORD_LOCK_TIME UNLIMITED配合FAILED_LOGIN_ATTEMPTS默认 10 次实现永久锁定避免暴力破解。3.2 授予精准视图权限非角色逐个 GRANT-- 必须显式 GRANT不能用 CONNECT 或 SELECT_CATALOG_ROLE权限过大 GRANT SELECT ON V_$INSTANCE TO monitor_user; GRANT SELECT ON V_$DATABASE TO monitor_user; GRANT SELECT ON V_$TABLESPACE TO monitor_user; GRANT SELECT ON DBA_TABLESPACE_USAGE_METRICS TO monitor_user; GRANT SELECT ON V_$LISTENER_NETWORK TO monitor_user; GRANT SELECT ON V_$ARCHIVE_DEST_STATUS TO monitor_user; GRANT SELECT ON V_$SESSION TO monitor_user; GRANT SELECT ON V_$SQLAREA TO monitor_user; GRANT SELECT ON DBA_REGISTRY_HISTORY TO monitor_user; -- 检查补丁应用状态 -- 如果需查锁等待额外授权谨慎 -- GRANT SELECT ON V_$LOCK TO monitor_user; -- GRANT SELECT ON V_$SESSION_WAIT TO monitor_user;所有视图前缀为V_$带下划线而非V$同义词——因为V$同义词依赖PUBLIC角色而PUBLIC可能被误删DBA_TABLESPACE_USAGE_METRICS是 Oracle 11.2 新增视图比老式DBA_TABLESPACESDBA_DATA_FILES计算更准且无需SYS.DBA_*权限绝对不授SELECT ANY DICTIONARY该权限等价于SELECT_CATALOG_ROLE可查SYS.USER$等敏感基表属高危权限。3.3 验证权限是否生效用监控用户登录后执行最小测试集# 切换到 monitor_user 测试 sqlplus monitor_user/Kx8#mQ2!pL//192.168.10.10:1521/ORCL SQL SELECT INSTANCE_NAME, STATUS FROM V$INSTANCE; SQL SELECT TABLESPACE_NAME, USED_PERCENT FROM DBA_TABLESPACE_USAGE_METRICS WHERE ROWNUM1; SQL SELECT COUNT(*) FROM V$SESSION WHERE STATUSACTIVE; -- 若任一报 ORA-00942: table or view does not exist则说明 GRANT 缺失立即补授测试必须用实际连接串执行不能只在 SQL*Plus 里CONNECT / AS SYSDBA后切用户——那会继承 SYS 权限掩盖真实权限问题ROWNUM1是关键技巧避免大表全扫快速验证视图可访问性。4. 避坑指南巡检脚本上线后踩过的 5 个真实坑每一条都让 DBA 加班到凌晨巡检脚本最大的陷阱不是写不出来而是「看起来跑通了实则漏报、误报、卡死、泄密」。以下是我在生产环境踩出的血泪坑按发生频率排序4.1 坑脚本在 Linux 后台运行时Oracle 连接报 ORA-12154TNS:could not resolve service name现象手动执行python check_oracle.py成功但nohup python check_oracle.py 后报错Excel 为空。原因oracledbThin 模式虽不依赖 client但仍需解析tnsnames.ora或连接字符串。后台进程继承的$ORACLE_HOME为空导致//host:port:sid格式解析失败尤其当 SID 含-或_时。解决强制使用 Easy Connect Plus 语法并在连接字符串中显式指定?serverTypededicated# 错误写法依赖 tnsnames.ora conn oracledb.connect(prod_db) # 正确写法完全自包含 dsn 192.168.10.10:1521/ORCL?serverTypededicated conn oracledb.connect(usermonitor_user, passwordKx8#mQ2!pL, dsndsn)4.2 坑Excel 报告打开后提示「发现不可读取的内容」修复后数据丢失现象openpyxl生成的.xlsx在 Windows Excel 打开报错Mac Numbers 打开正常。原因openpyxl3.1 版本默认启用keep_vbaFalse但某些 Excel 模板尤其含图表隐式依赖 VBA 引擎强行关闭导致结构损坏。解决生成时显式禁用 VBA 保存并用write_onlyTrue模式提升大表性能from openpyxl import Workbook wb Workbook(write_onlyTrue) # 仅写模式内存友好 # ... 写入逻辑 ... wb.save(output_path) # 注意write_only 模式不支持图表嵌入需用常规模式 关闭 VBA4.3 坑巡检脚本并发跑 3 个实例其中一个卡死整个进程 hang 住现象max_workers3但prod_db连接超时后test_db和dev_db也迟迟不返回。原因oracledb默认连接超时为None无限等待网络抖动时conn oracledb.connect(...)卡死阻塞线程池。解决为每个连接显式设置connection_timeout和query_timeoutpool oracledb.create_pool( usermonitor_user, passwordKx8#mQ2!pL, dsn192.168.10.10:1521/ORCL, min1, max3, increment1, connection_timeout30, # 连接建立超时秒 getmodeoracledb.POOL_GETMODE_WAIT )4.4 坑V$SESSION查出 2000 会话Excel 写入耗时 5 分钟报告生成失败现象脚本执行到check_long_running_sql()时内存暴涨Python 报MemoryError。原因pandas.read_sql()默认将整张V$SESSION加载进内存而该视图在繁忙库可达数万行。解决用chunksize分块读取 流式处理# 不要这样 # df pd.read_sql(SELECT * FROM V$SESSION, conn) # 要这样 chunks [] for chunk in pd.read_sql(SELECT SID, SERIAL#, STATUS, USERNAME, PROGRAM FROM V$SESSION, conn, chunksize500): active_count len(chunk[chunk[STATUS] ACTIVE]) chunks.append({ACTIVE_COUNT: active_count, TOTAL: len(chunk)}) summary pd.DataFrame(chunks).sum()4.5 坑config.ini里密码含#脚本静默读取为空字符串连不上库现象脚本无报错但所有检查项passFalse日志显示Connection failed。原因configparser将#视为注释起始符monitor_user:Kx8#mQ2!pL被截断为Kx8。解决两种方式二选一推荐用双引号包裹密码 ——monitor_user:Kx8#mQ2!pL备选改用toml格式更现代天然支持特殊字符[instances.prod_db] host 192.168.10.10 port 1521 sid ORCL user monitor_user password Kx8#mQ2!pL # TOML 原生支持5. 进阶实战用巡检报告驱动日常运维决策——不只是「看一眼」而是「做判断」巡检的价值不在生成报告而在报告如何改变你的工作流。我见过太多团队把巡检当成「打卡任务」脚本跑完Excel 存档再无下文。真正高效的团队会把巡检数据变成运维决策的燃料。以下是我落地的 3 个具体技巧全部基于本方案生成的 Excel 报告。5.1 技巧一用 Excel Power Query 自动合并多日报告生成容量趋势图每天的report_20240520.xlsx只是快照但连续 30 天的数据才能看出问题。手动复制粘贴太原始。用 Power QueryExcel 内置 ETL 工具自动拉取新建空白 Excel → 数据选项卡 → 「从文件夹」→ 选择./reports/目录筛选文件名含report_的.xlsx展开Content列 → 点击「转换数据」进入 Power Query 编辑器添加自定义列提取日期Date.FromText(Text.Middle([Name],7,8))假设文件名report_20240520.xlsx展开Sheet1表空间使用率页→ 提取TABLESPACE_NAME,USED_PERCENT,Date关闭并上载 → 自动生成透视表 折线图横轴日期纵轴使用率图例为表空间名。效果某次发现USERS表空间使用率从 65% → 82% → 91% 三日连涨立刻排查发现某应用日志表未分区及时加了按月分区策略避免了下周的宕机。5.2 技巧二把「异常项」自动转为工单对接 ITSM 系统以 Jira 为例报告里的 ❌ FAIL 不是终点而是工单起点。用 Python 调 Jira API 自动创建# jira_ticket.py from jira import JIRA import pandas as pd def create_jira_ticket(failed_checks): jira JIRA(serverhttps://your-jira.com, basic_auth(user, api_token)) for item in failed_checks: summary f[巡检告警] {item[section]} 异常{item[detail]} description f *实例*{item[instance]} *时间*{pd.Timestamp.now().strftime(%Y-%m-%d %H:%M)} *详情* {item[raw_data].to_markdown(indexFalse)} *建议操作*{item[suggestion]} issue jira.create_issue( projectDBA, summarysummary, descriptiondescription, issuetype{name: Incident}, priority{name: High if ⚠️ in item[detail] else Medium} ) print(fJira ticket created: {issue.key}) # 在主脚本中调用 failed_items [r for r in check_results if not r[pass]] if failed_items: create_jira_ticket(failed_items)priority动态设置含⚠️的项标为 High推动快速响应description用 Markdown 渲染raw_dataJira 原生支持比纯文本易读百倍。5.3 技巧三用巡检结果反向优化数据库配置真实案例某次巡检发现V$SQLAREA中PARSE_CALLS/EXECUTIONS比值长期 5说明硬解析过多共享池压力大。这不是脚本 bug而是数据库配置问题检查项当前值建议值依据shared_pool_size1G2GV$SGASTAT中free memory 100MBcursor_sharingEXACTFORCE应用 SQL 绑定变量使用率低session_cached_cursors50200V$SESSTAT中session cursor cache count高频命中我们据此出具《数据库参数优化建议书》经 DBA 团队评审后实施次日library cache hit ratio从 89% 提升至 99.2%应用平均响应时间下降 37%。我的习惯是每次巡检报告生成后花 10 分钟扫一遍 Summary 页的 ❌ 项问自己三个问题这是偶发还是持续查历史报告这是配置问题、应用问题、还是硬件问题结合V$OSSTAT、V$SYSMETRIC能否用一条 SQL 或一个参数调整解决优先选最小改动真正的运维不是救火而是让火永远烧不起来。希望帮到你。本文还有配套的精品资源点击获取
返回列表