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

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

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


文章目录

转变

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

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

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

sql 复制代码
ALTER SYSTEM SET memory_target=4G SCOPE=SPFILE;

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

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

sql 复制代码
-- SGA大小
ALTER SYSTEM SET sga_target=3G SCOPE=SPFILE;

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

再细一点:

sql 复制代码
-- 共享池(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。

sql 复制代码
SELECT sql_text, executions, parse_calls
FROM v$sqlarea
WHERE parse_calls > executions;

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

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

2. 数据缓冲区太小

症状:磁盘读取频繁。

sql 复制代码
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. 排序溢出到磁盘

症状:排序操作慢。

sql 复制代码
SELECT name, value
FROM v$sysstat
WHERE name IN ('sorts (memory)', 'sorts (disk)');

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


二、关键参数配置

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

游标相关的参数

sql 复制代码
-- 每个会话能打开的游标数
ALTER SYSTEM SET open_cursors=300 SCOPE=SPFILE;

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

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

进程和会话数

sql 复制代码
-- 最大进程数
ALTER SYSTEM SET processes=500 SCOPE=SPFILE;

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

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

undo相关

sql 复制代码
-- undo保留时间(秒)
ALTER SYSTEM SET undo_retention=900 SCOPE=SPFILE;

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

日志相关

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

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


三、性能监控

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

sql 复制代码
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)每隔一段时间自动采集数据库状态快照。生成报告:

sql 复制代码
-- 查看快照列表
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报告很长,重点看几个部分:

  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

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查执行计划:

sql 复制代码
SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR('sql_id_here'));

锁阻塞

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

sql 复制代码
SELECT sid, serial#, blocking_session, wait_class, event, seconds_in_wait
FROM v$session
WHERE blocking_session IS NOT NULL;

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

sql 复制代码
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>;

必要时杀掉阻塞的会话:

sql 复制代码
ALTER SYSTEM KILL SESSION 'sid,serial#' IMMEDIATE;

四、备份策略

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

RMAN备份

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

全库备份:

bash 复制代码
rman target /

RMAN> BACKUP DATABASE PLUS ARCHIVELOG;

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

bash 复制代码
RMAN> BACKUP INCREMENTAL LEVEL 0 DATABASE;  -- 基础备份
RMAN> BACKUP INCREMENTAL LEVEL 1 DATABASE;  -- 增量备份

建议的备份策略

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

保留策略:

bash 复制代码
RMAN> CONFIGURE RETENTION POLICY TO RECOVERY WINDOW OF 7 DAYS;

保留7天的恢复窗口。

验证备份能恢复

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

bash 复制代码
RMAN> RESTORE DATABASE VALIDATE;
RMAN> RESTORE ARCHIVELOG ALL VALIDATE;

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

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

bash 复制代码
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的物理备份,还有逻辑备份(导出数据):

bash 复制代码
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$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 #备份策略

相关推荐
Albert Edison几秒前
【Redis】Centos7.9 安装 Redis 5 教程
数据库·redis·缓存
云计算磊哥@17 分钟前
运维开发宝典026-MySQL02数据库表操作
运维·数据库·运维开发
小二·32 分钟前
Redis 内存溢出(OOM)排查与恢复实战
数据库·redis·bootstrap
pqk6V6Vep33 分钟前
Redis 分布式锁进阶第一篇讲解
数据库·redis·分布式
giaz14n9X1 小时前
Redis 分布式锁进阶第六十一篇
数据库·redis·分布式
是一个Bug1 小时前
MongoDB:像搭积木一样存数据
数据库·mongodb
ULIi096kr1 小时前
MySQL解决Too many connections报错:连接数爆满排查、优化与永久解决方案
数据库·mysql·adb
SL-staff2 小时前
(一)数据源配置 —— JVS-Rules规则引擎 V2.5 操作说明介绍
数据库·jar·规则引擎·数据源·jvs-rules·api 接口·jvs低代码
摇滚侠3 小时前
Spring 零基础入门到进阶 基于 XML 管理 Bean 14-28
xml·数据库·spring
Metaphor6923 小时前
使用 Python 给 PDF 设置背景色或背景图
数据库·python·pdf