尧图精选

深入理解Oracle体系架构:物理存储、逻辑结构与实例内存全解析

🕒 发布时间:2026/9/2 11:32:16 📁 来源:尧图网络
1. 这篇文章真正要解决的问题很多刚接触 Oracle 的人或者从 MySQL 转过来的开发同学都会在同一个地方卡住明明学会了建表、写 SQL、做增删改查可一到面试、看 AWR 报告、或者生产环境出故障时面对“体系架构”这几个字还是一头雾水。更尴尬的是网上关于 Oracle 体系架构的文章很多但大多数要么直接翻译官方文档概念堆了一堆看完记不住要么只讲一幅大图把 SGA、PGA、表空间、数据文件这些名词列出来然后就没有然后了。真正让人困惑的问题很少有人讲透为什么 Oracle 里有“数据库”和“实例”两个概念它们到底什么关系物理体系和虚拟体系逻辑体系有什么区别为什么 Oracle 要这样设计执行一条 SQL从输入到返回结果数据到底经历了哪些环节为什么有人动不动就让你看 AWR 报告、查 V$ 视图这些视图和体系架构有什么关系作为开发或 DBA理解了架构之后到底能解决什么实际问题这篇文章不打算复述一遍官方架构图。我的做法是从 DBA 和开发在真实环境最常遇到的困惑出发把 Oracle 的物理体系、虚拟体系逻辑体系、实例内存结构和 SQL 执行链路拆开讲清楚并且每一部分都给出对应的查询命令和常见问题排查方式。读完这篇文章你应该能做到清楚区分 Oracle 的物理结构与逻辑存储知道 SGA 和 PGA 各自管什么能解释为什么一条 SQL 在 Oracle 里会走那么多步骤并且知道在遇到表空间不足、日志频繁切换、连接数爆满这类问题时应该先去查哪个视图。2. Oracle 体系架构的核心概念物理体系和虚拟体系先给一个判断Oracle 体系架构最核心的思想就是把“数据存在哪里”和“我们用什么样的逻辑视图去管理它”彻底分开了。这句话是整个 Oracle 架构理解的分水岭。2.1 物理体系数据最终落在哪里物理体系指的是操作系统层面真实存在的文件。Oracle 数据库的物理文件主要有三类文件类型作用文件后缀示例重要性数据文件Data File真正存放表和索引数据.dbf核心数据控制文件Control File记录数据库结构信息包括数据文件位置、日志文件信息、检查点信息.ctl丢失可能导致数据库无法启动重做日志文件Redo Log File记录所有数据修改操作用于崩溃恢复.log数据安全最后防线此外还有参数文件spfile / pfile、密码文件、归档日志文件等它们共同构成 Oracle 的物理层。物理文件直接对应操作系统中的一个真实文件。如果做过冷迁移也就是把数据库文件从一个机器拷贝到另一台机器你一定记得不仅要把数据文件带上还要带上控制文件和重做日志文件而且路径不能随便乱放。Oracle 在启动时会根据控制文件中的记录去找数据文件和日志文件路径对不上就会报错比如常见的ORA-00205控制文件错误。物理体系的重点在于它是真实存在于磁盘上的、看得见的文件结构。备份恢复了不了解物理文件后面的所有逻辑概念都谈不上。2.2 虚拟体系逻辑存储结构数据库内部怎么组织数据与物理文件对应的是 Oracle 的逻辑存储结构。逻辑结构是用户在 Oracle 内部“看到”和操作的对象它在物理文件之上建立了一层抽象Oracle 逻辑存储结构层级如下数据库Database └── 表空间Tablespace └── 段Segment └── 区Extent └── 数据块Data Block数据块Data BlockOracle 最小的存储单位通常为 8KB。对应操作系统块通常为 512 字节或 4KBOracle 块可能包含多个 OS 块。区Extent一组连续的数据块。段扩容时按区为单位分配空间。段Segment一个对象占用的所有区的集合。一张表、一个索引分别对应一个段。表空间Tablespace逻辑存储的最高层一个表空间对应物理上的一个或多个数据文件。表空间与数据文件的对应关系就是虚拟体系与物理体系之间最重要的桥梁。-- 查看当前数据库的所有表空间及其对应数据文件 SELECT t.tablespace_name, d.file_name, d.bytes / 1024 / 1024 AS size_mb FROM dba_tablespaces t JOIN dba_data_files d ON t.tablespace_name d.tablespace_name;理解了逻辑存储和物理存储的分离你就会明白很多日常操作背后的原理为什么CREATE TABLE可以指定TABLESPACE users因为你是在逻辑层创建对象实际落盘位置由表空间对应的数据文件决定。为什么ALTER TABLESPACE users ADD DATAFILE /u01/oracle/users02.dbf SIZE 1G;可以扩容因为表空间容量不够时可以新增数据文件然后再由 Oracle 把逻辑空间分配给段。为什么冷迁移时路径不能乱改因为表空间与数据文件的映射关系记录在控制文件中路径变了Oracle 找不到物理文件。2.3 实例Instance与数据库Database的区别这是 Oracle 初学者最容易混淆的概念也是面试高频题。数据库Database指物理文件集合包括数据文件、控制文件、重做日志文件。数据持久化在这里。实例Instance指 Oracle 的内存结构和后台进程的集合。实例是“活”的部分数据库是“死”的部分。两者的关系是实例可以挂载和打开一个数据库。一个实例同一时间只能操作一个数据库但一个数据库可以被多个实例操作——这就是 RACReal Application Clusters集群模式多个实例访问同一套物理文件。日常开发中你常听到的“启动数据库”准确说法应该是先启动实例实例再挂载数据库最后打开数据库。启动阶段 1. 实例启动数据库未挂载读取参数文件分配 SGA启动后台进程 2. 挂载数据库根据控制文件信息建立实例与数据库的关联 3. 打开数据库数据文件和日志文件可读可写可以对外提供服务用命令验证一下-- 查看当前实例信息 SELECT instance_name, status, database_status FROM v$instance; -- 查看当前数据库信息 SELECT name, dbid, created, open_mode FROM v$database; -- 查看 RAC 场景下所有实例如果有多个节点 SELECT inst_id, instance_name, status FROM gv$instance;为什么非要分清它们因为很多运维问题就出在“只启动了实例没有打开数据库”或者反过来。比如你在做ALTER DATABASE OPEN之前实例已经存在但数据库还没对外可用ORA-01034: ORACLE not available经常就是实例或数据库没有正常启动导致的。3. 实例内部结构SGA、PGA 与后台进程如果说物理体系和逻辑体系解决了“数据怎么存”的问题那么实例结构解决的就是“数据怎么在内存里流转”的问题。Oracle 实例 共享内存SGA 进程内存PGA/服务进程私有区 后台进程。3.1 SGASystem Global Area系统全局区SGA 是一块共享内存区域所有连接该实例的会话都能访问。SGA 的几个关键组件组件作用备注Database Buffer Cache缓存从磁盘读出的数据块所有数据读写先经过它Redo Log Buffer缓存重做日志记录防止每条修改立即写磁盘Shared Pool缓存 SQL 执行计划、数据字典信息由 Library Cache 和 Data Dictionary Cache 组成Large Pool供大容量操作使用比如并行查询、RMAN缓解 Shared Pool 压力Java Pool支撑 Java 存储过程一般不深究Streams Pool支撑 Oracle 流复制从 10g 开始常见SGA 的核心设计思想是“磁盘读取成本远高于内存读取”所以尽可能把热数据放在内存里减少磁盘 I/O。查看 SGA 各组件的实际大小SELECT * FROM v$sga; -- 更详细的组件分布 SELECT component, current_size, min_size, max_size FROM v$sga_dynamic_components ORDER BY component;在 12c 之前的版本中SGA 和 PGA 都有独立的大小参数SGA_MAX_SIZE、SGA_TARGET、PGA_AGGREGATE_TARGET。到了 12c 及以后Oracle 引入了内存自动管理可以把MEMORY_TARGET设置为一个总预算让实例自己决定 SGA 和 PGA 怎么分。但这个自动分配在多数生产环境中仍然建议保守使用具体原因在最佳实践部分会展开。3.2 PGAProgram Global Area程序全局区PGA 是服务进程私有的内存区域每个会话/进程都有自己的 PGA不是共享的。它主要用于排序操作ORDER BY、GROUP BY、DISTINCTHash 连接位图合并大字段LOB操作有一个高频面试题排序到底是在内存还是磁盘做答案是优先在 PGA 内做如果排序数据量超过了 PGA 的工作区限制PGA_AGGREGATE_TARGET和固定空间大小决定就会把中间结果写到临时表空间临时段也就是磁盘排序。全表扫描大量数据时也可能直接把数据放在 PGA 里处理而不是 SGA 的 Buffer Cache。查看 PGA 相关统计SELECT name, value FROM v$pgastat WHERE name IN ( aggregate PGA target parameter, aggregate PGA auto target, total PGA allocated, global memory bound );判断是否需要关注 PGA一句话就够如果 AWR 报告里出现大量的temp disk sort或者PGA memory相关等待事件就该考虑调整PGA_AGGREGATE_TARGET了。3.3 后台进程Oracle 自己雇的“搬运工”后台进程是实例的一部分它们负责在内存和磁盘之间搬运数据、维护数据库一致性。重点记住几个进程全称作用什么时候触发工作DBWR / DBWnDatabase Writer把 Buffer Cache 中被修改的脏块写回磁盘数据文件检查点、脏块过多、主动写LGWRLog Writer把 Redo Log Buffer 中的日志记录写入重做日志文件事务提交、缓冲区 1/3 满、超时CKPTCheckpoint更新控制文件和数据文件头部的检查点信息供恢复用周期性触发SMONSystem Monitor实例启动时做实例恢复日常清理临时段实例启动、系统管理PMONProcess Monitor监控并清理异常终止的进程恢复空闲连接进程崩溃时ARCnArchiver重做日志切换时写归档日志处于归档模式且发生日志切换想看看真实环境中有哪些后台进程可以执行SELECT paddr, program, pid, spid FROM v$process WHERE background 1;或者更直观一点在 Linux 上直接用操作系统命令查ps -ef | grep ora_你会看到类似ora_dbw0_orcl、ora_lgwr_orcl、ora_smon_orcl、ora_pmon_orcl这样的名字。ora_后面跟的进程名就对应上面这些后台进程最后的orcl是实例名。3.4 小结论SGA 解决“多会话共享数据缓存”PGA 解决“单会话私有数据操作”后台进程解决“内存与磁盘的数据交换”。三者协同Oracle 才能做到高性能读写和崩溃恢复。4. 关键环节REDO 与 UNDO、缓冲机制与检查点如果把 Oracle 体系架构比作一座城市SGA 是中央广场后台进程是各类工作人员那么 REDO 和 UNDO 就是两条必须分清的“地下通道”。4.1 REDO 日志所有修改的保险单REDO Log 记录的是“对数据做了什么修改”它的目的只有一个保证修改不丢失。当一条 UPDATE 语句执行时Oracle 会先在 SGA 中修改 Buffer Cache 中的数据并且生成一条 REDO 记录写入 Redo Log Buffer。事务提交时LGWR 才把 Redo Log Buffer 写到磁盘的重做日志文件中。这里有一个非常重要的细节事务提交时Oracle 并不会立刻把修改后的数据块写回磁盘数据文件——这是 DBWR 的工作而且可能延迟发生。真正保证提交不丢失的是 REDO 日志已经写盘。一旦数据库崩溃Oracle 可以凭借 REDO 日志把已经提交但还没落盘的数据重新恢复出来。这就是为什么重做日志文件不能和数据文件放在同一块磁盘上的根本原因——如果磁盘损坏同时影响数据文件和日志文件恢复就会非常困难。日常开发中如何查看 REDO 相关信息-- 查看日志切换频率 SELECT TO_CHAR(first_time, YYYY-MM-DD HH24) AS hour, COUNT(*) AS log_switches FROM v$log_history WHERE first_time SYSDATE - 7 GROUP BY TO_CHAR(first_time, YYYY-MM-DD HH24) ORDER BY hour; -- 查看当前日志组和状态 SELECT group#, thread#, sequence#, status, bytes FROM v$log;日志切换太频繁通常是好事还是坏事要看情况。如果每小时切换几十上百次说明 REDO 日志太小或事务量非常大频繁触发 LGWR 写盘会带来不必要的 I/O 开销。这是 DBA 调优中比较常见的一项。4.2 UNDO 回滚段后悔药UNDO 与 REDO 名字相近但作用完全不同。UNDO 记录的是“修改之前的旧值”用于事务回滚ROLLBACK读一致性多版本读闪回查询Flashback Query如果每个事务都对应一个独立“后悔药”空间Oracle 就是用 UNDO 表空间来统一管理这些旧值。日常开发中常见的问题就是一条 SQL 执行时间太长报出ORA-01555 snapshot too old这就是 UNDO 保存的旧版本数据被覆盖导致查询无法读取一致性快照。查看 UNDO 表空间使用情况SELECT tablespace_name, status, SUM(bytes) / 1024 / 1024 AS size_mb FROM dba_undo_extents GROUP BY tablespace_name, status; -- 查看 UNDO 保留时间参数 SHOW PARAMETER undo_retention;合理设置UNDO_RETENTION和 UNDO 表空间大小可以避免大部分快照过旧问题。但这也要结合业务场景不是一味调大就合理。4.3 检查点Checkpoint机制检查点是一个“安全边界”。发生检查点时DBWR 会把 Buffer Cache 中的脏块写回数据文件同时 CKPT 进程更新控制文件和数据文件头部的检查点位置。检查点的意义在于崩溃恢复时Oracle 只需要从最近一次检查点开始应用后面的 REDO 日志而不需要从开工第一天开始重放所有日志。检查点越频繁恢复时间越短但写磁盘压力越大检查点越稀疏日常写入性能越好但崩溃恢复时间越长。这就是一个典型的性能与恢复时间的权衡。5. 执行一条 SQL从客户端到返回结果的完整链路理解了上述组件之后最有效的巩固方式就是跟着一条 SQL 走完整条链路。假设有一条更新语句UPDATE emp SET salary salary * 1.1 WHERE dept_id 10;这条语句在 Oracle 内部大致经历以下阶段客户端发送 SQL通过监听器Listener建立到 Oracle 实例的连接。常见工具是 SQL*Plus、PL/SQL Developer、Navicat、DBeaver 等。这一步涉及监听器配置和网络协议Oracle Net。会话建立与认证Oracle 在实例侧创建服务进程前台进程用户提交用户名密码。注意Oracle 的认证信息存放在数据字典中除了常见的密码认证还有操作系统认证适用于管理员。SQL 解析Parse先在 Shared Pool 的 Library Cache 中查找是否有相同文本的执行计划软解析还是硬解析。如果找不到则进行硬解析检查语法、检查语义和权限、通过优化器选择执行计划。硬解析成本远高于软解析。这也是为什么大量使用 SQL 拼接不绑定变量会导致 Shared Pool 压力大、出现大量解析等待的原因。绑定与执行如果 SQL 使用绑定变量此时会替换变量值然后服务进程开始执行计划读取涉及的数据块。读取时先看 Buffer Cache 是否有缓存块缓存没有则从数据文件读入 Buffer Cache。生成 REDO 和 UNDO修改前把旧值写入 UNDO 段同时生成一条 UNDO 记录的 REDO因为 UNDO 也是数据修改也需要 REDO 保护。修改 Buffer Cache 中的 data block。生成 REDO 记录写入 Redo Log Buffer。事务提交CommitLGWR 把 Redo Log Buffer 中的记录写入重做日志文件。提交成功返回给客户端成功信息。注意提交时并不保证数据文件已经写入新值。数据块落盘由 DBWR 按检查点机制异步完成。客户端获取结果如果是查询语句SELECT服务进程把结果集返回给客户端如果是 DML则返回影响行数。这条链路几乎贯穿了体系架构中的所有核心组件。如果你想更深入地了解某一条 SQL 的具体执行统计可以用-- 开启 SQL 跟踪生产环境谨慎使用需要 DBA 权限 ALTER SESSION SET sql_trace TRUE; -- 执行 SQL SELECT * FROM emp WHERE dept_id 10; -- 关闭跟踪 ALTER SESSION SET sql_trace FALSE;然后在 user_dump_dest 目录下找到 trace 文件可以看到解析时间、执行时间、物理读、逻辑读、排序等详细数据。这是最直接的学习素材。6. 从体系架构角度理解日常运维问题这一部分回答大家最想知道的问题理解了架构之后生产环境遇到故障该怎么查6.1 表空间不足现象执行 SQL 报ORA-01653: unable to extend table ... by ... in tablespace ...。理解段要扩容需要新的区但表空间已没有空闲空间或已经是自动扩展上限。排查SELECT tablespace_name, used_space, tablespace_size, used_percent FROM dba_tablespace_usage_metrics ORDER BY used_percent DESC;解决方案扩大数据文件大小或开启自动扩展建议设置合理的 maxsize。增加数据文件。如果是临时表空间不足报错会是ORA-01652需要给临时表空间加文件或扩容。6.2 连接数满现象应用报ORA-12518: TNS:listener could not hand off client connection。理解进程数和会话数达到限制或者监听器无法分配新进程。排查-- 查看当前会话数 SELECT COUNT(*) FROM v$session; -- 查看进程数 SELECT COUNT(*) FROM v$process; -- 查看连接数限制 SHOW PARAMETER processes; SHOW PARAMETER sessions;解决方案调整processes、sessions参数需要重启实例12c 之后部分参数可以动态调整。从应用侧增加连接池限制避免无限创建连接。杀掉异常空闲会话谨慎操作先确认会话状态。6.3 日志切换频繁现象AWR 报告中log file sync和log file parallel write等待事件偏高磁盘写压力大。理解LGWR 写日志的等待影响到了应用层提交速度。排查思路查看日志切换频率是否过高。查看重做日志文件是否过小。解决方案增大日志文件大小。增加日志组数量。改善日志文件的磁盘 I/O使用独立的高速存储。6.4 硬解析过高现象CPU 占用高AWR 报告中 Library Cache 相关等待多。理解应用没有使用绑定变量每条 SQL 都触发硬解析。排查-- 查看 Library Cache 命中率 SELECT gethitratio, pinhitratio FROM v$librarycache WHERE namespace SQL AREA;解决方案应用层使用绑定变量。使用游标共享CURSOR_SHARINGFORCE作为临时降级方案但不是推荐长期方案。优化连接池减少连接反复建立。这里要特别提醒CURSOR_SHARINGFORCE也许能快速解决硬解析问题但可能导致执行计划变差、出现安全边界模糊等问题。生产环境一定要评估。7. Oracle 体系架构常见疑问汇总表问题现象可能原因排查方向解决方案ORA-01034: ORACLE not available实例未启动或数据库未打开查看v$instance和v$database按启动阶段逐步启动实例、挂载并打开数据库ORA-01157/ORA-01110数据文件丢失或路径不一致查v$datafile、控制文件恢复文件或从备份恢复数据文件ORA-01555UNDO 记录被覆盖查看undo_retention和 UNDO 表空间大小调大 UNDO 表空间适当延长保留时间ORA-01653表空间不足查看表空间使用率扩容或增加数据文件ORA-12518连接数满或监听器问题查看processes、sessions调整连接参数优化应用连接池log file sync等待高LGWR 写日志慢或日志频繁切换查看日志切换频率和磁盘 I/O增大日志文件、改善磁盘性能硬解析过多未使用绑定变量查看 Library Cache 命中率应用改造结合绑定变量这些问题的共性是如果只停留在“报错就重启、大不了扩容”的层面永远无法真正解决问题。理解了体系架构你才能判断问题出在物理层磁盘、文件、内存层SGA、PGA、还是逻辑层表空间、段、区。8. 最佳实践与工程建议8.1 开发和运维都应该记住的内存分配原则从开发者的角度如果一条 SQL 需要大量排序、分组或哈希连接尽量在应用层先把数据量缩小不要让 Oracle 在 PGA 中处理几十 GB 的中间结果。这不是 SQL 优化技巧而是资源规划意识。从 DBA 的角度如果MEMORY_TARGET开启自动内存管理在 OLTP 高并发场景下要观察 SGA 和 PGA 是否频繁自动调优这种变动本身也会带来额外开销。更稳妥的做法是先以手动指定SGA_TARGET和PGA_AGGREGATE_TARGET的方式运行一段时间收集基线数据后再决定是否交给自动管理。8.2 SQL 编写层面的体系思维理解了 Shared Pool 和 Library Cache 之后你就明白为什么 Oracle 教育大家要使用绑定变量-- 不推荐每条 SQL 都是一个新字符串全部硬解析 SELECT * FROM emp WHERE emp_id 1001; SELECT * FROM emp WHERE emp_id 1002; -- 推荐使用绑定变量同一条 SQL 复用执行计划 PREPARE stmt FROM SELECT * FROM emp WHERE emp_id ?; EXECUTE stmt USING 1001; EXECUTE stmt USING 1002;这背后的原理就是SQL 文本完全一致时软解析才能命中否则就只能走硬解析。这是体系架构直接指导 SQL 开发的典型例子。8.3 关于备份和恢复最重要的一句话物理体系决定了备份的粒度。RMAN 备份的核心是备份数据文件、控制文件、归档日志逻辑备份expdp、impdp导出的是逻辑对象不是物理文件的拷贝。生产环境恢复时物理备份恢复速度快、可靠程度高逻辑备份更常用于数据迁移和对象备份。不要把 expdp 当作唯一的备份方案。8.4 运维操作的安全边界无论是ALTER TABLESPACE、DROP TABLE还是调整初始化参数在开发环境和测试环境验证通过后再上生产。任何涉及生产环境的变更都应该有备份、有回滚方案、有变更窗口。如果只是测试学习建议先在虚拟机搭一套单机 Oracle比如 19c 单实例反复练习启动、关闭、报错排查再上生产环境操作。很多经验必须靠踩坑积累而不是靠看文档。8.5 日志记录和监控建议体系架构的每个层面都值得监控物理层磁盘空间、数据文件状态、归档日志空间。内存层SGA 命中率、Buffer Cache 命中率、PGA 排序率。进程层会话数、进程数、活跃 SQL。等待事件层log file sync、db file sequential read、db file scattered read等。建议从系统上线第一天就使用 AWR 报告建立性能基线之后的每次优化都通过对比 AWR 报告来评估效果。9. 总结与后续学习方向这篇文章把 Oracle 体系架构拆成了几个关键部分物理体系数据文件、控制文件、重做日志文件回答“数据存在哪”。虚拟体系逻辑体系表空间、段、区、数据块回答“逻辑上怎么组织”。实例结构SGA、PGA 和后台进程回答“数据在内存里怎么流转”。关键机制REDO、UNDO、检查点回答“崩溃恢复和读一致性怎么保证”。SQL 执行链路从客户端到返回结果的完整流程把以上所有概念串起来。运维视角从架构理解表空间不足、连接数满、日志切换频繁等问题。接下来你可以按这个顺序继续深入先在虚拟机里装一个单实例 Oracle版本以实际项目为准用文中的命令把 V$ 视图、SGA 组件、后台进程查一遍。模拟一条慢 SQL打开 SQL Trace 看执行阶段的物理读和逻辑读。用 AWR 报告生成一次日常报表分析 Top 等待事件。再进一步学习执行计划EXPLAIN PLAN FOR和 SQL 优化器原理。把体系架构学扎实后你再去看V$视图、AWR 报告或任何 Oracle 性能问题时就不会只是背命令而是能真正判断“这个指标对应的是哪个组件、说明什么问题”。这一步一旦跨过去Oracle 的学习会顺畅很多。如果这篇文章对你有帮助建议收藏备用后续遇到体系架构相关问题可以回来对照排查。
上一篇/下一篇内容由系统自动关联 返回资讯列表 →