欢迎光临
我们一直在努力

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

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

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


文章目录

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

转变

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

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

  • 能用就行——SQL写对了就行,不管性能
  • 出事再救——查询慢了看执行计划,数据库挂了硬恢复
  • 提前预防——配好参数、建好监控、做好备份
  • 这篇讲的是从阶段二到阶段三的转变。


    一、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以后,可以用一个参数自动管理大部分内存:

    ALTER SYSTEM SET memory_target=4G SCOPE=SPFILE;

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

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

    — SGA大小
    ALTER SYSTEM SET sga_target=3G SCOPE=SPFILE;

    — PGA大小
    ALTER SYSTEM SET pga_aggregate_target=1G SCOPE=SPFILE;

    再细一点:

    — 共享池(SQL解析、执行计划缓存)
    ALTER SYSTEM SET shared_pool_size=512M SCOPE=SPFILE;

    — 数据缓冲区(数据块缓存)
    ALTER SYSTEM SET db_cache_size=1G SCOPE=SPFILE;

    — 日志缓冲区
    ALTER SYSTEM SET log_buffer=16M SCOPE=SPFILE;

    常见的内存问题

    1. 共享池太小

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

    SELECT sql_text, executions, parse_calls
    FROM v$sqlarea
    WHERE parse_calls > executions;

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

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

    2. 数据缓冲区太小

    症状:磁盘读取频繁。

    SELECT name, value
    FROM v$sysstat
    WHERE name IN ('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. 排序溢出到磁盘

    症状:排序操作慢。

    SELECT name, value
    FROM v$sysstat
    WHERE name IN ('sorts (memory)', 'sorts (disk)');

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


    二、关键参数配置

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

    游标相关的参数

    — 每个会话能打开的游标数
    ALTER SYSTEM SET open_cursors=300 SCOPE=SPFILE;

    — 会话缓存游标的数量(软解析用)
    ALTER SYSTEM SET session_cached_cursors=100 SCOPE=SPFILE;

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

    进程和会话数

    — 最大进程数
    ALTER SYSTEM SET processes=500 SCOPE=SPFILE;

    — 最大会话数(通常比processes大10%~20%)
    ALTER SYSTEM SET sessions=555 SCOPE=SPFILE;

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

    undo相关

    — undo保留时间(秒)
    ALTER SYSTEM SET undo_retention=900 SCOPE=SPFILE;

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

    日志相关

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

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


    三、性能监控

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

    SELECT event, total_waits, time_waited
    FROM v$system_event
    WHERE wait_class != 'Idle'
    ORDER BY time_waited DESC;

    常见的等待事件:

    等待事件含义可能的原因
    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)每隔一段时间自动采集数据库状态快照。生成报告:

    — 查看快照列表
    SELECT snap_id, begin_interval_time, end_interval_time
    FROM dba_hist_snapshot
    ORDER BY snap_id DESC;

    — 生成报告(在SQL*Plus中执行)
    @?/rdbms/admin/awrrpt.sql

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

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

    SELECT sql_id, sql_text, elapsed_time / 1000000 AS elapsed_sec,
    executions, elapsed_time / executions / 1000000 AS avg_sec
    FROM v$sql
    WHERE executions > 0
    ORDER BY elapsed_time DESC
    FETCH FIRST 20 ROWS ONLY;

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

    SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR('sql_id_here'));

    锁阻塞

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

    SELECT sid, serial#, blocking_session, wait_class, event, seconds_in_wait
    FROM v$session
    WHERE blocking_session IS NOT NULL;

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

    SELECT sid, serial#, sql_text
    FROM v$session s
    JOIN v$sql q ON s.sql_id = q.sql_id
    WHERE s.sid = <blocking_session>;

    必要时杀掉阻塞的会话:

    ALTER SYSTEM KILL SESSION 'sid,serial#' IMMEDIATE;


    四、备份策略

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

    RMAN备份

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

    全库备份:

    rman target /

    RMAN> BACKUP DATABASE PLUS ARCHIVELOG;

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

    RMAN> BACKUP INCREMENTAL LEVEL 0 DATABASE; — 基础备份
    RMAN> BACKUP INCREMENTAL LEVEL 1 DATABASE; — 增量备份

    建议的备份策略

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

    保留策略:

    RMAN> CONFIGURE RETENTION POLICY TO RECOVERY WINDOW OF 7 DAYS;

    保留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/tiger DIRECTORY=dp_dir DUMPFILE=kc22_%U.dmp TABLES=kc22 PARALLEL=4

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

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

    五、日常运维清单

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

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

    从救火到防火

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

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

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

  • 硬盘会坏
  • 内存会出错
  • 人会写错SQL
  • 电力会断
  • 下一篇,讲这些原理在不同数据库里的对应——从Oracle到MySQL到PostgreSQL,底层逻辑是不是同一套。


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

    赞(0)
    未经允许不得转载:171主机测评 » 开发转兼职DBA(五):从救火到防火——参数、内存、监控、备份
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址