暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

理解共享内存和信号量---Oracle数据库怎样分配使用共享内存及信号量

原创 听见风的声音 2023-04-26
809

共享内存和信号量对于unix上的Oracle 数据库实例来说,是两个非常重要的资源。如果一个实例不能分配它所需要的资源,这个实例将不能启动。

1 定义

共享内存正如它的名字,是一个可以在不同的进程之间共享的内存区域。Oracle使用共享内存来实现SGA,而SGA是需要对所有会话可见的。
信号量,可以被认为是信号旗(flag),也如它们的名字,semaphores(semaphores的英文意思是旗语,用双手或者两个旗子的不同位置表示不同的字母)。它们或者打开或者
关闭。进程可以打开信号量,也可以关闭它。如果一个信号量已经打开,尝试打开这个信号量的进程将进入睡眠状态直至这个信号量被关闭。在唤醒时,进程尝试重新打开信号量,
可能成功,也可能重新睡眠(打开信号量失败)。这个行为使信号量可以用来实现一个通知-等待驱动器(post-wait driver)—一个系统,系统里的进程可以等待事件(即等该打开
信号量)和通知事件(即打开信号量)。Oracle使用这个机制来维持对SGA的并发控制,因为所有连接到SGA的进程都可以对它进行写操作。

2 SGA分配简介

共享内存是Oracle实例必须的:在实例启动时,做的第一件事就是:读“init.ora”(Oracle实例参数文件),启动后台进程,分配所必须的共享内存和信号量,SGA的大小从init.ora 内的不同参数计算得到。这会是所需要的共享内存的数量。SGA被分为4各部分:固定部分,大小是固定的;可变部分,它的大小根据init.ora的不同而改变,redo 块缓冲区,它的大小是由日志缓冲区控制的;db块缓冲区,它的大小由db_block_buffers决定。SGA的大小是这四个部分大小的总和。不够幸运的是,没有简单的公式可以计算SGA的可变部分。
通常,共享池在可变内存中占主导低位,所以一个简单的办法是你可以将共享池的大小看作是SGA可变部分内存的大小。
决定Oracle需要的信号量的数量就要简单多了。Oracle需要和"init.ora"的process参数值相同的信号量数量。

3 共享内存分配

  • 1) 一个共享内存段
  • 2) 多个连续(相邻)共享内存段
  • 3) 多个不连续共享内存段
    当试图分配和连接共享内存时,按照上面的顺序尝试每一个模型,直到一个模型成功或者抛出Oracle ora错误。在这个过程中,一个方案失败,发生非致命的错误,Oracle简单的清理之后会尝试下一方案。整个SGA必须固定到共享内存中,所以任意模型分配的内存必须等于SGA的大小。

3.1 一个共享内存段

这是最简单的内存分配模型,也是最先尝试的模型。在这个模型中,SGA只存在于一个共享内存段中。Oracle试图分配和连接一个等于SGA大小的共享内存段。但是如果SGASIZE大于配置的SHMMAX,显然会失败。在这种情况下,SGA需要放置到多个的内存共享段中,Oracle继续尝试下一个方案。
多个共享段的情况下由两种可能性。这些连接的共享段可能连续的,因此它们看起来像一个大的共享段。或者是不连续的,段与段之间存在间隙。

3.2 多个连续的共享内存段

在连续段模型中,Oracle简单的将SGA划分到 SGASIZE/SHMMAX(向下取整)个SHMMAX大小的内存段加上一个SGASIZE除以 SHMMAX的余数大小的内存段中。

3.3 非连续多个内存段。

当内存段的大小和数量确定后,Oracle每一次分配和连接一个内存段;先是固定和可变内存部分的内存段,接着是redo 块缓冲内存段,借着是数据块缓冲内存段。这些连接的内存是不连续的。
在这个时间点,我们或者连接了所有SGA,或者返回一个ORA错误。连接的内存段的总大小等于SGASIZE,这里没有内存浪费。一旦Oracle连接了共享内存,它开始继续分配需要的信号量。

##Oracle 8i推荐的共享内存核心参数值 SHMMAX= 共享内存段的最大值 = .5 * 物理内存大小 SHMMIN= 共享内存段的最小值=1 SHMMNI= 共享内存标识符的最大数量 = 100 SHMSEG= 每个进程最大的共享内存段数量 = 10 ##一个共享内存段能创建的最大sga大小等于 SHMMAX*SHMSEG

你可以使用"sysdef -i"来显示共享内存的当前值。

4 信号量分配

Oracle仅仅需要分配刚好和init.ora中process参数值相等数量的信号量。

SEMMSL= # 一个信号集中的信号量 SEMMNI= the maximum # 系统中最大信号集数量 SEMMNS= 系统中信号量的总数 SEMOPM= 每个 semop 调用的最大操作数 = 100 SEMVMX = 信号量最大值 = 32767

当实例启动时,所有的必须的信号量将被分配。信号量被分配到信号集中。
因为每一Oracle 进程需要一个信号量,分配的数量等于参数文件中的process的值。需要的信号量的数量等于所有实例的process参数值的总和。
你可以分配所有的信号量到一个信号集,或者是多个信号集中。如果SEMMSL=processes,那么只需要一个信号集。
如果SEMMSL不等于processes,确保需要的信号量的总数不会超过SEMMNI*SEMMSL和SEMMNS的最大值。
举一个例子,如果SEMMSL=25,SEMMNI=10,所需要的信号量不能超过250.
注意:有些操作系统有最大信号量的设置。
如果你有多个实例,这些实例的processes的设置了不同的值,你可能想设置SEMMSL等于最大的processes值,从而避免分配不会被使用的信号量。否则,
这可能会阻止你分配所有必须的信号量。
比如下面的例子:
Instance PROD 参数 PROCESSES=100
Instance DEV 参数 PROCESSES=50
如果SEMMSL = 50,将会分配3个信号集,prod实例2个,dev实例一个。
如果SEMMSL = 100,将会分配两个信号集,prod实例一个,dev实例一个。在这个例子中,dev实例分配了100个信号量,它只会使用50个。它不使用的50个
信号量不能用于其它数据库。
要看到什么信号量被分配, 使用 ‘ipcs -b’.
例如:

Semaphores: T ID KEY MODE OWNER GROUP NSEMS s 0 0 --ra-r----- osupport dba 25 s 1 0 --ra-r----- osupport dba 25 s 18 0 --ra-r----- osupport dba 25 s 19 0 --ra-r----- osupport dba 25 s 4 0 --ra-r----- osupport dba 25 s 5 0 --ra-r----- osupport dba 25 ##NSEMS=每一个信号集中的信号量数量.

在每一已经启动且正在运行的系统中运行下面这些命令

$ svrmgrl SVRMGR>connect internal SVRMGR>oradebug ipc

将会显示每一运行的实例连接和使用的每一个共享内存段和信号量
oradebug ipc 命令的输出示例

-------------- Shared memory -------------- Seg Id Address Size 10250 c1eaf000 4591616 Total: # of segments = 1, size = 4591616 -------------- Semaphores ---------------- Total number of semaphores = 50 Number of semaphores per set = 50 Number of semaphore sets = 1 Semaphore identifiers: 188434

Seg Id 10250显示的是连接至运行实例的共享内存。不要移除它。
Semaphore identifiers 188434显示的是运行实例连接的信号量。不要移除它。
当你记下了所有运行实例连接的内存和信号量标识符后,和ipcs -b显示的数值比较一下。
没有运行实例匹配的条目是孤儿条目,需要被移除。移除这些条目的命令是ipcrm
注意: 移除 共享内存 和 信号量的选项是不同的.

ipcrm -m <== 用来移除共享内存 ipcrm -s <== 用来移除信号量条目

原文标题:Understanding Shared Memory and Semaphores
原文作者:Nidhi Jain
原文地址:https://www.orafaq.com/node/8

最后修改时间:2023-04-26 09:20:10
「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论