当前位置: 首页 > news >正文

开发转兼职DBA(五):从救火到防火——参数、内存、监控、备份

开发转兼职DBA(五):从救火到防火——参数、内存、监控、备份

前面两篇都是数据库起不来了硬恢复。这篇讲怎么从"出事再救"转向"提前预防"——参数配置、内存结构、性能监控、备份策略。


文章目录

  • 开发转兼职DBA(五):从救火到防火——参数、内存、监控、备份
    • 转变
    • 一、Oracle的内存结构
      • SGA——所有进程共享的内存
      • PGA——每个进程独占的内存
      • 哪些参数控制这些内存
      • 常见的内存问题
    • 二、关键参数配置
      • 游标相关的参数
      • 进程和会话数
      • undo相关
      • 日志相关
    • 三、性能监控
      • 等待事件——判断瓶颈在哪
      • AWR报告——全面体检
      • 找到慢SQL
      • 锁阻塞
    • 四、备份策略
      • RMAN备份
      • 建议的备份策略
      • 验证备份能恢复
      • expdp/impdp——逻辑备份
    • 五、日常运维清单
    • 从救火到防火

转变

两次数据库起不来的事故之后,我意识到一个事实:每次都是出了事才学,每次都是在生产环境上赌命。

开发者面对数据库的态度,通常有三个阶段:

  1. 能用就行——SQL写对了就行,不管性能
  2. 出事再救——查询慢了看执行计划,数据库挂了硬恢复
  3. 提前预防——配好参数、建好监控、做好备份

这篇讲的是从阶段二到阶段三的转变。


一、Oracle的内存结构

调参数之前,得先知道数据库的内存是怎么组织的。

Oracle的内存分两大块:SGA(System Global Area)和PGA(Program Global Area)。

SGA——所有进程共享的内存

SGA ├── Database Buffer Cache(数据缓冲区) │ └── 存数据块的副本,减少磁盘读取 ├── Redo Log Buffer(日志缓冲区) │ └── 存redo记录,提交时刷到redo log文件 ├── Shared Pool(共享池) │ ├── Library Cache(库缓存)——存SQL的解析结果和执行计划 │ └── Data Dictionary Cache(数据字典缓存)——存表结构、索引信息 ├── Large Pool(大池,可选) │ └── RMAN备份、并行查询等大块操作 └── Java Pool(Java池,可选) └── JVM相关

PGA——每个进程独占的内存

PGA ├── SQL工作区(排序、哈希连接用的内存) ├── 会话信息 └── 游标状态

哪些参数控制这些内存

Oracle 10g以后,可以用一个参数自动管理大部分内存:

ALTERSYSTEMSETmemory_target=4G SCOPE=SPFILE;

Oracle自动在SGA和PGA之间分配。简单,但不够精细。

手动管理模式——更可控:

-- SGA大小ALTERSYSTEMSETsga_target=3G SCOPE=SPFILE;-- PGA大小ALTERSYSTEMSETpga_aggregate_target=1G SCOPE=SPFILE;

再细一点:

-- 共享池(SQL解析、执行计划缓存)ALTERSYSTEMSETshared_pool_size=512M SCOPE=SPFILE;-- 数据缓冲区(数据块缓存)ALTERSYSTEMSETdb_cache_size=1G SCOPE=SPFILE;-- 日志缓冲区ALTERSYSTEMSETlog_buffer=16M SCOPE=SPFILE;

常见的内存问题

1. 共享池太小

症状:SQL执行慢,但不是查询本身慢——是每次都要重新解析SQL。

SELECTsql_text,executions,parse_callsFROMv$sqlareaWHEREparse_calls>executions;

如果parse_calls接近executions,说明SQL几乎每次都在重新解析。可能的原因:

  • 共享池太小,缓存的执行计划被挤掉了
  • SQL没有用绑定变量,每次都是硬解析

2. 数据缓冲区太小

症状:磁盘读取频繁。

SELECTname,valueFROMv$sysstatWHEREnameIN('db block gets from cache','consistent gets from cache','physical reads');

计算命中率:

命中率 = 1 - (physical reads / (db block gets from cache + consistent gets from cache))

命中率低于90%,考虑增大数据缓冲区。

3. 排序溢出到磁盘

症状:排序操作慢。

SELECTname,valueFROMv$sysstatWHEREnameIN('sorts (memory)','sorts (disk)');

如果sorts (disk)不为0,说明排序在内存里放不下,溢出到临时表空间了。增大PGA或pga_aggregate_target


二、关键参数配置

除了内存参数,还有几个影响数据库行为的参数。

游标相关的参数

-- 每个会话能打开的游标数ALTERSYSTEMSETopen_cursors=300SCOPE=SPFILE;-- 会话缓存游标的数量(软解析用)ALTERSYSTEMSETsession_cached_cursors=100SCOPE=SPFILE;

游标数太小,会报ORA-01000: maximum open cursors exceeded。但不要设太大——每个游标都占共享池内存。

进程和会话数

-- 最大进程数ALTERSYSTEMSETprocesses=500SCOPE=SPFILE;-- 最大会话数(通常比processes大10%~20%)ALTERSYSTEMSETsessions=555SCOPE=SPFILE;

政务系统并发用户多、连接池大,默认值150经常不够。

undo相关

-- undo保留时间(秒)ALTERSYSTEMSETundo_retention=900SCOPE=SPFILE;

undo_retention=900意味着Oracle尝试保留undo数据至少15分钟。用于闪回查询(Flashback Query)和一致性读。设置太短,长查询可能遇到ORA-01555: snapshot too old

日志相关

-- 日志切换的间隔(秒)-- 如果日志切换太频繁(几分钟一次),考虑增大日志文件大小ALTERSYSTEMSETarchive_lag_target=1800SCOPE=SPFILE;

日志文件大小在建库时设定,不能动态改。一般建议日志切换间隔15~30分钟。


三、性能监控

等待事件——判断瓶颈在哪

SELECTevent,total_waits,time_waitedFROMv$system_eventWHEREwait_class!='Idle'ORDERBYtime_waitedDESC;

常见的等待事件:

等待事件含义可能的原因
db file sequential read单块读等待索引访问大量数据,可能索引选择不当
db file scattered read多块读等待全表扫描
log file sync日志同步等待提交太频繁
buffer busy waits缓冲区忙等待热块竞争
enq: TX - row lock contention行锁等待事务冲突
latch: shared pool共享池锁存器竞争硬解析太多

db file sequential read→ 检查索引是否合理,是不是走了不该走的索引。

db file scattered read→ 检查是否有不该全表扫描的查询。

log file sync→ 检查是否有频繁提交的循环逻辑,考虑批量提交。

enq: TX - row lock contention→ 检查是否有多个事务同时改同一行。

AWR报告——全面体检

Oracle的AWR(Automatic Workload Repository)每隔一段时间自动采集数据库状态快照。生成报告:

-- 查看快照列表SELECTsnap_id,begin_interval_time,end_interval_timeFROMdba_hist_snapshotORDERBYsnap_idDESC;-- 生成报告(在SQL*Plus中执行)@?/rdbms/admin/awrrpt.sql

AWR报告很长,重点看几个部分:

  1. Top 10 Foreground Events——数据库时间花在哪了
  2. SQL ordered by Elapsed Time——最慢的SQL
  3. SQL ordered by Gets——消耗最多逻辑读的SQL
  4. Segment by Physical Reads——读取最多的表/索引
  5. Tablespace I/O——表空间的I/O情况

找到慢SQL

SELECTsql_id,sql_text,elapsed_time/1000000ASelapsed_sec,executions,elapsed_time/executions/1000000ASavg_secFROMv$sqlWHEREexecutions>0ORDERBYelapsed_timeDESCFETCHFIRST20ROWSONLY;

找到慢SQL后,拿sql_id查执行计划:

SELECT*FROMTABLE(DBMS_XPLAN.DISPLAY_CURSOR('sql_id_here'));

锁阻塞

用户说"操作卡住了",先查锁:

SELECTsid,serial#, blocking_session, wait_class, event, seconds_in_waitFROMv$sessionWHEREblocking_sessionISNOTNULL;

blocking_session字段告诉你谁在阻塞谁。找到阻塞源头:

SELECTsid,serial#, sql_textFROMv$sessionsJOINv$sqlqONs.sql_id=q.sql_idWHEREs.sid=<blocking_session>;

必要时杀掉阻塞的会话:

ALTERSYSTEMKILLSESSION'sid,serial#'IMMEDIATE;

四、备份策略

前面两次事故都是因为没有备份才那么狼狈。恢复成功是运气,不是能力。

RMAN备份

Oracle的标准备份工具是RMAN(Recovery Manager)。

全库备份:

rman target / RMAN>BACKUP DATABASE PLUS ARCHIVELOG;

增量备份(只备份变化的数据块):

RMAN>BACKUP INCREMENTAL LEVEL0DATABASE;-- 基础备份 RMAN>BACKUP INCREMENTAL LEVEL1DATABASE;-- 增量备份

建议的备份策略

每天凌晨:增量备份(LEVEL 1) 每周日凌晨:全量备份(LEVEL 0) 每小时:归档日志备份

保留策略:

RMAN>CONFIGURE RETENTION POLICY TO RECOVERY WINDOW OF7DAYS;

保留7天的恢复窗口。

验证备份能恢复

备份不做恢复测试等于没备份。

RMAN>RESTORE DATABASE VALIDATE;RMAN>RESTORE ARCHIVELOG ALL VALIDATE;

VALIDATE只验证备份文件是否完整可读,不做实际恢复。

定期在测试环境做真实的恢复演练——恢复到指定时间点:

RMAN>RUN{SET UNTIL TIME"TO_DATE('2024-01-15 14:00:00', 'YYYY-MM-DD HH24:MI:SS')";RESTORE DATABASE;RECOVER DATABASE;ALTER DATABASE OPEN RESETLOGS;}

expdp/impdp——逻辑备份

除了RMAN的物理备份,还有逻辑备份(导出数据):

expdp scott/tigerDIRECTORY=dp_dirDUMPFILE=kc22_%U.dmpTABLES=kc22PARALLEL=4

逻辑备份不能做媒体恢复(磁盘坏了不能用它恢复),但适合:

  • 迁移数据
  • 只恢复个别表
  • 跨版本导出

五、日常运维清单

把以上内容整合成日常要做的事:

频率做什么怎么做
每天检查告警日志adrci或直接读alert_<SID>.log
每天检查表空间使用率SELECT * FROM dba_tablespace_usage_metrics;
每天检查备份是否成功SELECT * FROM v$rman_status;
每周查看AWR报告@?/rdbms/admin/awrrpt.sql
每周查看慢SQLv$sqlelapsed_time排序
每月收集统计信息DBMS_STATS.GATHER_DATABASE_STATS
每月检查无效对象SELECT * FROM dba_objects WHERE status='INVALID';
每季度恢复演练测试环境做RMAN恢复

从救火到防火

前面四篇,前两篇是性能问题(执行计划、索引),后两篇是可靠性问题(redo损坏、undo损坏)。都是出了事才处理。

这篇讲的——参数配置、内存结构、性能监控、备份策略——是让事尽量不出。

但现实中,防火做得再好,也要准备救火的工具。因为:

  1. 硬盘会坏
  2. 内存会出错
  3. 人会写错SQL
  4. 电力会断

下一篇,讲这些原理在不同数据库里的对应——从Oracle到MySQL到PostgreSQL,底层逻辑是不是同一套。


标签:#DBA #Oracle #参数配置 #内存结构 #SGA #PGA #性能监控 #AWR #RMAN #备份策略

http://www.cnnetsun.cn/news/2608072.html

相关文章:

  • ESP32实战指南:NVS非易失性存储数据持久化与结构体存储
  • FModel完全指南:高效提取虚幻引擎游戏资源的实用工具
  • Cortex-R4处理器nCPUHALT信号原理与应用解析
  • 算法与数据结构概述
  • LLM应用安全实战:构建IPI-Scanner防御间接提示注入攻击
  • Redis应用场景深度解析
  • ABAQUS作业XML解析失败:从报错信息到资源调优的实战排查
  • 【力扣100题】62.滑动窗口最大值
  • 读了 GPT-4 分词器源码才明白:为什么 tiktoken 宁可丢掉合并树,也要采用“只读字典”的扁平设计?
  • GPU编程能效优化:从数据传递到源码级能耗感知实践
  • 从搜索引擎到推荐系统:TF-IDF算法在Python中的实战场景全解析
  • 不只是小乌龟:用Gazebo和UUV Simulator打造你的第一个水下机器人仿真项目
  • 深入Unity动画底层:拆解Playable Graph与ScriptPlayable,实现自定义动画逻辑
  • 从开题到定稿零障碍!用 okbiye 搞定毕业论文全流程
  • 手把手教你用ModBus RTU控制汇川SV660P伺服电机(附CRC16校验C代码)
  • 2026微信小游戏开发者大会发布最新数据,各类型小游戏表现亮眼!
  • 智能制造的关键入口:从传统视觉到AI智能体视觉(系列)
  • 终极指南:如何在Android手机上解锁微信双设备登录,实现工作生活分离
  • 缠论量化框架chan.py:3大核心技术突破实现自动化交易革命
  • ChatGPT旅行规划辅助必须关闭的4个默认参数,否则行程可靠性下降67%(NIST旅行数据可信度白皮书实证)
  • 迭代扰动粒子滤波:突破重采样瓶颈,实现并行化贝叶斯状态估计
  • Azure云服务智能工具与数据库定价优化实战指南
  • 浏览器里的飞行实验室:零门槛玩转无人机日志分析
  • 如何用Python命令行工具突破百度网盘下载限速:完整实战指南
  • 多速率信号处理源码深度剖析
  • Analog Devices ADSP-TS201SABPZ060:TigerSHARC 600MHz DSP技术规格与设计参考
  • 向量数据库与RAG管道:本质区别与构建健壮系统的五大核心代价
  • 全双工大规模MIMO中联合波束成形与天线选择的自干扰抑制技术
  • 五子棋AI对战平台搭建指南:整合强化学习模型与PyGame可视化界面
  • 分数阶Sigma-Delta调制器设计与实现【附代码】