Oracle数据库实例之内存架构(一)

  • Oracle数据库内存结构
    • 基本内存结构
    • Oracle内存管理
  • 用户全局区:UGA
  • 程序全局区:PGA
    • PGA的内容
    • 专用和共享服务器模式下的PGA
  • 系统全局区:SGA

本文讨论的内容涉及的数据库版本为 12.2。

Oracle数据库内存结构

数据库实例启动后,Oracle数据库会为其分配一块内存区域并启动相关后台进程。该内存区域存储了以下信息:

  • 程序代码
  • 已连接会话(session)的信息,即使该session当前并未处于活跃状态;
  • 程序执行过程中所需的信息,比如查询(query)的当前状态;
  • 进程之间共享和通信的(lock data)相关的信息;
  • 缓存数据(cached data),比如数据块、重做记录等从磁盘中读取的信息。

基本内存结构

Oracle数据库中的基本内存结构包括:

  • 系统全局区(System global area, SGA
    SGA是一组共享内存,其中包含了数据库实例的数据和控制信息。所有的服务器和后台进程都会共享SGA。SGA中的数据包括缓存数据块、共享SQL区等。

  • 程序全局区(Program global area, PGA
    PGA是非共享的内存区域,其中包含了一个Oracle进程独占使用的数据和控制信息。当有一个Oracle进程启动时,Oracle数据库就会创建一个PGA。对于每个服务器进程(server process)和后台进程,都会存在一个对应的PGA。所有单独的PGA的集合构成了总的实例PGA(instance PGA)。数据库的初始化参数(在参数文件 spfile 中)决定了PGA实例的大小,而不是每个单独的PGA。

  • 用户全局区(User global area, UGA)
    UGA是与一个用户会话(user session)相关的内存。

  • 软件代码区(Software code areas)
    软件代码区是用于存储正在运行或者可以运行的代码。Oracle数据库代码存储在与用户程序不同的地方。

下图展示了以上内存结构之间的关系。

图1 Oracle数据库内存结构

Oracle内存管理

内存管理(memory management)涉及到在对数据库的需求发生变化时,维护Oracle实例内存结构的最佳大小。Oracle数据库基于与内存相关的初始化参数配置来管理内存。内存管理的基本可选项包括以下内容:

  • 自动内存管理(automatic memory management)
    需要明确设置数据库实例内存的目标大小。数据库实例会自动调整到目标内存大小,并按需在SGA和实例PGA之间分配内存。

  • 自动共享内存管理(automatic shared memory management)
    该模式为部分自动内存管理。你需要为SGA设定目标大小,然后为实例PGA设定总的目标大小,但是你也可以单独管理PGA。

  • 手动内存管理(manual memory management)
    该模式下,你需要设定许多初始化参数来单独管理SGA和实例PGA。

如果你用数据库配置助手(Database Configuration Assistant, DBCA)来创建数据库,并选择了基本的安装选项,那么默认的内存管理方式为自动内存管理。

用户全局区:UGA

UGA是一块为会话变量(session variables)分配的内存,比如登录信息等其他数据库会话需要的信息。本质上,UGA存储了session的状态。

图2 UGA结构

如果一个会话向内存中载入了PL/SQL包(PL/SQL package),那么UGA中就包含了包的状态,即某个时刻该包里所有变量存储的的一组值。当该包的一个子程序修改了变量的值,包的状态也会改变。包的变量默认是唯一的,且在会话的生存时间内存在。

UGA中还存储了OLAP页池(OLAP page pool)。这个页池会管理OLAP数据页(数据块)。该页池在OLAP会话启动时被分配,在会话结束时被释放。OLAP会话会在用户查询维度对象(比如数据立方体 cube)时自动打开。

UGA必须在会话生存时间内可用。因此,使用共享服务器(shared server)连接时,UGA不能存储在PGA中。因为PGA只与单个进程相关。此时,UGA存储在SGA中,使得任意一个共享服务器进程都能访问它。相反地,当使用专用服务器(dedicated server)连接时,UGA就存储在PGA中。

程序全局区:PGA

PGA是针对系统中一个非共享的进程(process)或线程(thread)的内存,不会在SGA中分配。PGA是存储了一个专用或共享服务器进程所需的会话变量的堆内存(memory heap)。服务器进程分配它在PGA中所需的内存结构。

下图展示了一个实例PGA。你可以通过初始化参数来设置实例PGA的最大目标大小。组成实例PGA的所有单个的PGA会按需自动增长到该目标值。

图3 PGA实例结构

PGA的内容

PGA被划分为几个不同的区域。下图展示了一个专用服务器会话对应的PGA内容。

图4 PGA结构

第一部分:私有SQL区
私有SQL区(private SQL area)存有经过语法分析的SQL语句(parsed SQL statement)的信息、以及其他针对会话的信息。当服务器进程执行SQL或PL/SQL代码时,该进程会使用私有SQL区来存储绑定变量(bind variable)的值、查询执行状态、以及查询执行工作区的信息。

切忌不要混淆私有SQL区(在PGA中)和共享SQL区(在SGA中,用于存储执行计划)。同一个或者不同的会话中的多个私有SQL区可以指向SGA中的一个执行计划。但是这些私有SQL区彼此之间并不共享,其中包含的值和数据也可能不一样。

游标(cursor)是一个具体的私有SQL区的名称或者句柄(handle)。可以把游标认为是客户端的一个指针和服务器端的一个状态。考虑到二者联系紧密,有时候游标和私有SQL区这两个名词会互换着使用。

图5 游标

私有SQL区可以分为以下两个部分:

  • 运行时区(run-time area)
    运行时区包含了查询的执行状态信息。比如,运行时区会追踪在全表扫描(full table scan)中截至到当前已获取的行的数目。Oracle数据库在执行请求的第一步就会创建运行时区。对于DML操作而言,运行时区会在SQL语句关闭时释放。

  • 持久区(persistent area)
    持久区包含绑定变量的值。绑定变量的值会在执行SQL语句时传递给处于运行时的SQL语句。只有在游标关闭时,持久区才会被释放。

客户端进程负责管理私有SQL区。私有SQL区的分配和回收很大程度上取决于应用,尽管一个客户端进程能够分配的私有SQL区的数量会受到初始化参数 OPEN_CURSORS 的限制。通常来说,应用应该关闭所有不再使用的游标,以释放持久区来最小化应用用户所需的内存。

第二部分:SQL工作区
工作区(work area)是用于内存密集型操作而分配的一块私有PGA内存。例如,一个排序运算子使用排序区(sort area)来给行排序。一个哈希连接运算子(hash join operator)使用一块哈希区来创建哈希表。位图合并(bitmap merge)则使用位图合并区来合并多次位图索引扫描获取的数据。

下面展示了两个表 employeesdepartments 的连接操作及其对应的查询计划。运行时区负责跟踪全表扫描的过程。当前会话执行一个哈希连接操作来匹配两个表的行。ORDER BY 排序则发生在排序区。

SQL> SELECT * 2  FROM   employees e JOIN departments d 3  ON     e.department_id=d.department_id 4  ORDER BY last_name;
.
.
.
--------------------------------------------------------------------------------
| Id| Operation           | Name        | Rows  | Bytes | Cost (%CPU)| Time    |
--------------------------------------------------------------------------------
| 0 | SELECT STATEMENT    |             |   106 |  9328 |    7  (29)| 00:00:01 |
| 1 |  SORT ORDER BY      |             |   106 |  9328 |    7  (29)| 00:00:01 |
|*2 |   HASH JOIN         |             |   106 |  9328 |    6  (17)| 00:00:01 |
| 3 |    TABLE ACCESS FULL| DEPARTMENTS |    27 |   540 |    2   (0)| 00:00:01 |
| 4 |    TABLE ACCESS FULL| EMPLOYEES   |   107 |  7276 |    3   (0)| 00:00:01 |
--------------------------------------------------------------------------------

如果运算子处理的数据的量超过了工作区的容量,Oracle数据库就会把输入数据分割成更小的部分。这样数据库就能在内存中先处理一部分数据,而把剩余的部分放在临时的磁盘空间中留待之后处理。

当自动PGA内存管理模式开启时,数据库会自动地调整工作区的大小。当然你也可以手动控制调整工作区的大小。通常来说,更大的工作区能够显著提升运算子的性能,同时也会消耗更多的内存。

专用和共享服务器模式下的PGA

PGA的内存分配取决于数据库使用的是专用的还是共享的服务器连接。

内存区 专用服务器 共享服务器
会话内存是否共享 私有 共享
持久区的位置 PGA SGA
DML和DDL语句的运行时区的位置 PGA PGA

系统全局区:SGA

SGA是一块可读写内存区域,与Oracle后台进程(background processes)一起构成了数据库实例。所有代表用户执行的服务器进程都能读取实例SGA里的信息。有一些进程能在数据库运行时写入SGA。需要注意的是,服务器和后台进程本身并不在SGA中,而是存在于独立的内存空间中。

每个数据库实例都有自己的SGA。Oracle数据库会在实例启动时自动为SGA分配内存,并在实例关闭时回收内存。正如图1,SGA由多个为了满足特定内存分配需求的内存池组成。除了重做日志缓存(redo log buffer)以外,所有其他的内存池都按连续内存单位分配和回收内存空间。这个连续内存单位称之为粒(granule),其大小与平台有关且取决于总的SGA大小。

查询 V$SGASTAT 视图可以看到SGA各部分的信息。其中包括数据库缓存、IM区、重做日志缓存、共享池、Large池、Java池、Streams池、固定SGA等。

SGA更详细的内容请参考:Oracle数据库实例之内存架构(二)。

References
[1] https://docs.oracle.com/en/database/oracle/oracle-database/12.2/cncpt/memory-architecture.html#GUID-0788EAEE-0E93-497B-9ACA-401EC0F7BCA1

Oracle数据库实例之内存架构(一)相关推荐

  1. Oracle数据库实例之进程架构(二)

    Oracle数据库实例之进程架构(二) 必需的后台进程 PMON PMAN LREG SMON DBW LGWR CKPT MMON & MMNL RECO 可选的后台进程 ARCn CJQ0 ...

  2. 修改linux下全局数据库名,linux/unix下修改oracle数据库实例名的方法

    linux/unix下修改oracle数据库实例名的方法 2018年12月10日 | 萬仟网IT编程 | 我要评论 linux/unix下修改oracle实例名的方法 1.检查原来的数据库实例名 $ ...

  3. 2. Oracle 数据库实例启动关闭过程

    转载自: http://blog.csdn.net/leshami/article/details/5542983 Oracle数据库实例的启动,严格来说应该是实例的启动,数据库仅仅是在实例启动后进行 ...

  4. Oracle数据库实例的创建、删除、修改

    以SUSE10SP2.Oracle10gR2为例. 本文中的数据库实例这一称谓应该换做数据库更为准确,数据库可以理解为是一个物理的静态概念,主要包括一些物理存在的数据库文件,而数据库实例则是一个动态概 ...

  5. oracle监听 客户 实例,oracle 数据库实例 监听

    创建Oracle数据库.数据库名与实例名与SID之间的关系(图文详解) 目录 目录 软件环境 前言 安装Oracle监听程序 启动停止监听程序 创建数据库 数据库名db_name 数据库实例名inst ...

  6. Oracle 数据库实例启动关闭过程

    --================================ -->Oracle 数据库实例启动关闭过程 --================================ /* Or ...

  7. Linux无界面创建Oracle数据库实例

    Linux创建Oracle数据库实例 上一篇安装了数据库,本文记录创建数据库实例步骤 1.安装步骤: 内存检查 : 内存检查,如果过小,则会报错,具体错误可以看最后的问题列表,我初始内存为2G,出错之 ...

  8. Linux无界面新建Oracle数据库实例

    Linux无界面新建Oracle数据库实例 根据https://blog.csdn.net/qq_24058757/article/details/88220437 步骤操作后总结整理的自己的新建实例 ...

  9. CentOS Linux 新建oracle数据库实例并连接

    CentOS Linux 新建oracle数据库实例 安装好oracle之后,首先想到的那就是自己建一个库来看看效果喽. 创建的过程如下文章所说,http://blog.chinaunix.net/u ...

最新文章

  1. Servlet和JSP规范及版本对应关系
  2. 原型共享数据 原型简单语法 原型中方法是可以相互访问 实例对象属性方法层层搜索
  3. 讲讲数据分析中的同期群模型
  4. jakarta ee_Jakarta EE 8状态
  5. spring集成jndi_Spring应用程序与JNDI连接池的集成测试
  6. Mybatis源码分析之(四)mapper访问数据库的底层原理(代理方法中具体访问数据库的细节)
  7. 什么是心跳线?心跳线,主要用于主从服务器之间,是连接工作机与备份机的网线
  8. 程序员利用测试账户套现千万美元,或面临20年监禁
  9. Yaffs2根文件系统制作
  10. UVa——110303 Common Permutation(字符串)
  11. js中元素属性值的获取
  12. bzoj 1924 所驼门王的宝藏
  13. [Angular2 Animation] Control Undefined Angular 2 States with void State
  14. Spring3注解零配置【私塾在线原创】
  15. C语言自制小游戏:三子棋(井字棋)游戏(超详细)
  16. R语言—基本统计分析
  17. 华为手机助手 android,华为手机助手(安卓版)
  18. adf盖怎么打开_兄弟7470d显示ADF盖打开是什么问?
  19. Three.js光源梳理3——平行光(DirectionalLight)
  20. python关于变量的声明

热门文章

  1. 2022年氯化工艺考试内容及氯化工艺考试报名
  2. 第98讲:使用SBT开发时动手解决rt.jar中CharSequence is broken等问题学习笔记
  3. 线性回归预测PM2.5
  4. Android Studio做登录界面
  5. 眉山市职称计算机成绩,眉山市2014年第2次(4月份)全国职称计算机考试成绩.doc
  6. 2022广州国际食品饮料包装展览会
  7. 80核处理器_Intel i9-10980XE处理器首发评测:售价“良心”的18核性能旗舰
  8. 2021-06-11 智能汽车和自动驾驶行业人才状态初探
  9. 爬取汽车之家汽车品牌型号系列数据
  10. picoCTF Web1