最近频繁遇到共享内存的问题,这里总结一下一些设置:
cat /proc/sys/kernel/shmmax
cat /proc/sys/kernel/shmmni
cat /proc/sys/kernel/shmall
临时修改这三个参数的值,通过echo或sysctl命令修改proc文件中的值,重启失效
echo 1073741824 > /proc/sys/kernel/shmmax
sysctl -w kernel.shmmax=1073741824 # 1GB
echo "kernel.shmmax=1073741824" 》 /etc/sysctl.conf
我们可以修改shmmax内核参数,使SGA存在于一个共享内存段中。
通过修改/proc/sys/kernel/shmmax参数可以达到此目的。
[root@neirong root]# echo 1073741824 > /proc/sys/kernel/shmmax
[root@neirong root]# more /proc/sys/kernel/shmmax
1073741824这里设为1G。
对于shmmax文件的修改,系统重新启动后会复位。可以通过修改 /etc/sysctl.conf 使更改永久化。
在该文件内添加以下一行 kernel.shmmax = 1073741824 这个更改在系统重新启动后生效.
1、设置 SHMMAX
SHMMAX
参数定义共享内存段的最大尺寸(以字节为单位)。在设置 SHMMAX 时,切记 SGA 的大小应该适合于一个共享内存段。 SHMMAX 设置不足可能会导致以下问题:
ORA-27123:unable to attach to shared memory segment
您可以通过执行以下命令来确定 SHMMAX 的值:
# cat /proc/sys/kernel/shmmax
33554432
SHMMAX 的默认值是 32MB 。我一般使用下列方法之一种将 SHMMAX 参数设为 2GB :
通过直接更改 /proc 文件系统,你不需重新启动机器就可以改变 SHMMAX 的默认设置。我使用的方法是将以下命令放入 /etc/rc.local 启动文件中:
# >echo "2147483648" > /proc/sys/kernel/shmmax
您还可以使用 sysctl 命令来更改 SHMMAX 的值:
# sysctl -w kernel.shmmax=2147483648
最后,通过将该内核参数插入到 /etc/sysctl.conf 启动文件中,您可以使这种更改永久有效:
# echo "kernel.shmmax=2147483648" >> /etc/sysctl.conf
2、设置 SHMMNI
我们现在来看 SHMMNI 参数。这个内核参数用于设置系统范围内共享内存段的最大数量。该参数的默认值是 4096 。这一数值已经足够,通常不需要更改。
您可以通过执行以下命令来确定 SHMMNI 的值:
# cat /proc/sys/kernel/shmmni
4096
3、设置 SHMALL
最后,我们来看 SHMALL 共享内存内核参数。该参数控制着系统一次可以使用的共享内存总量(以页为单位)。简言之,该参数的值始终应该至少为:
ceil(SHMMAX/PAGE_SIZE)
SHMALL 的默认大小为 2097152 ,可以使用以下命令进行查询:
# cat /proc/sys/kernel/shmall
2097152
SHMALL 的默认设置对于我们的 Oracle9 i RAC 安装来说应该足够使用。
注意: 在 i386 平台上 Red Hat Linux 的 页面大小 为 4096 字节。但是,您可以使用 bigpages ,它支持配置更大的内存页面尺寸
这是实际linux系统显示的实际数据:
beijibing@bjb-desktop:/proc/sys/kernel$ cat shmmax
33554432
beijibing@bjb-desktop:/proc/sys/kernel$ cat shmmni
4096
beijibing@bjb-desktop:/proc/sys/kernel$ cat msgmax
8192
beijibing@bjb-desktop:/proc/sys/kernel$ cat msgmni
622
beijibing@bjb-desktop:/proc/sys/kernel$ cat msgmnb
16384
System V IPC 参数
名字 | 描述 | 合理取值 |
---|---|---|
SHMMAX | 最大共享内存段尺寸(字节) | 最少若干兆(见文本) |
SHMMIN | 最小共享内存段尺寸(字节) | 1 |
SHMALL | 可用共享内存的总数量(字节或者页面) | 如果是字节,就和 SHMMAX 一样;如果是页面,ceil(SHMMAX/PAGE_SIZE) |
SHMSEG | 每进程最大共享内存段数量 | 只需要 1 个段,不过缺省比这高得多。 |
SHMMNI | 系统范围最大共享内存段数量 | 类似 SHMSEG 加上用于其他应用的空间 |
SEMMNI | 信号灯标识符的最小数量(也就是说,套) | 至少ceil(max_connections / 16) |
SEMMNS | 系统范围的最大信号灯数量 | ceil(max_connections / 16) * 17 加上用于其他应用的空间 |
SEMMSL | 每套信号灯最小信号灯数量 | 至少 17 |
SEMMAP | 信号灯映射里的记录数量 | 参阅文本 |
SEMVMX | 信号灯的最大值 | 至少 1000 (缺省通常是32767,除非被迫,否则不要修改) |
最重要的共享内存参数是 SHMMAX , 以字节记的共享内存段可拥有的最大尺寸。如果你收到来自shmget
的类似Invalid argument 这样的错误信息,那么很有可能是你超过限制了。
有些系统对系统里面共享内存的总数(SHMALL )还有限制。 请注意这个数值必须足够大。(注意:SHMALL 在很多系统上是用页面数,而不是字节数来计算的。)
系统里的最大信号灯数目是由SEMMNS 设置的,因此这个值应该至少和 max_connections 设置一样大,并且每十六个联接还要另外加一个。 参数SEMMNI 决定系统里一次可以存在的信号灯集的数目。 因此这个参数至少应该为 ceil(max_connections % 16) 。降低允许的联接数目是一个临时的绕开失败的方法,这个启动失败通常被来自函数semget
的错误响应 No space left on device 搞得很让人迷惑。
有时候还可能有必要增大SEMMAP ,使之至少按照 SEMMNS 配置。这个参数定义信号灯资源映射的尺寸,可用的每个连续的信号灯块在这个映射中存放一条记录。每当一套信号灯被释放,那么它要么会加入到该映射中一条相连的已释放的块的入口中,要么注册成一条新的入口。如果映射填满了碎片,那么被释放的信号灯就丢失了(除非重起)。因此时间长信号灯空间的碎片了会导致可用的信号灯比应该有的信号灯少。
SEMMSL 参数,决定一套信号灯里可以有多少信号灯,
更改方法
缺省设置只适合小安装(缺省最大共享内存是 32 MB)。不过,其它的缺省值都相当大,通常不需要改变。最大的共享内存段设置可以用 sysctl 接口设置。 比如,要允许 128 MB,并且最大的总共享内存数为 2097152 页(缺省):
$
sysctl -w kernel.shmmax=134217728
$
sysctl -w kernel.shmall=2097152
你可以把这些设置放到 /etc/sysctl.conf 里,在重启后保持有效。
老版本里可能没有 sysctl 程序,但是同样的改变可以通过操作 /proc 文件系统来做:
$ echo 134217728 >/proc/sys/kernel/shmmax $ echo 2097152 >/proc/sys/kernel/shmall
在文件的前面注释的后面加入以下行:
#修改内核共享内存大小;
echo134217728>/proc/sys/kernel/shmmax;
#说明:这里的值为内存的一半;
#如果系统内存是256M,则值为134217728;
#如果系统内存是512M,则值为268435456;
修改完成以后,重起机器就搞定。
其它系统的修改方法
在 OS X 10.2 以及更造版本里, 编辑文件 /System/Library/StartupItems/SystemTuning/SystemTuning 并且用下列命令修改这些数值:
sysctl -w kern.sysv.shmmax sysctl -w kern.sysv.shmmin sysctl -w kern.sysv.shmmni sysctl -w kern.sysv.shmseg sysctl -w kern.sysv.shmall
在 OS X 10.3 及以后的版本里,这些命令移动到 /etc/rc 里面去了,必须在那里编辑。你需要重新启动才能让设置生效。请注意/etc/rc 通常会被 OS X 更新覆盖 (比如 10.3.6 到 10.3.7),所以每次更新后你可能都需要重新编辑。
在这个平台上,SHMALL 是用 4KB 页来度量的。 还要注意有些版本的 OS X 将拒绝把 SHMMAX 的数值数值为非 4096 的倍数。
缺省配置时,只允许每段 512KB 共享内存。 要增大设置,首先进入 /etc/conf/cf.d 目 录。要显示当前的以字节记的 SHMMAX ,运行
./configure -y SHMMAX
设置 SHMMAX 的新值:
./configure SHMMAX=value
这里 value 是你想设置的以字节记的新值。设置完了以后SHMMAX 重新制作内核
./link_unix
然后重起。
至少对于版本 5.1 而言,我们有必要为类似 SHMMAX 这样的参数做特殊的配置,因为这个参数可以配置为所有内容都当作共享内存使用。这就是类似 DB/2 这样的数据库常用的配置。
不过,我们可能有必要在 /etc/security/limits 里面修改全局 ulimit ulimit 信息,因为文件大小的缺省硬限制(fsize )以及文件数(nofiles )可能太低了。
至少到版本 2.6 为止,共享内存段的缺省最大设置对 PostgreSQL 来说是太低了。相关的设置可以在/etc/system 里面修改,例如:
set shmsys:shminfo_shmmax=0x2000000 set shmsys:shminfo_shmmin=1 set shmsys:shminfo_shmmni=256 set shmsys:shminfo_shmseg=256 set semsys:seminfo_semmap=256 set semsys:seminfo_semmni=512 set semsys:seminfo_semmns=512 set semsys:seminfo_semmsl=32
你要重起系统令修改生效。
又见 http://sunsite.uakom.sk/sunworldonline/swol-09-1997/swol-09-insidesolaris.html 获取关于 Solaris 里面的共享内存的信息。
在 UnixWare 7 上,缺省配置里的最大共享内存段是 512 kB。 要显示SHMMAX 的当前值,运行
/etc/conf/bin/idtune -g SHMMAX
就会显示以字节记的当前的缺省的最小和最大值。 要给SHMMAX 设 置一个新值,运行:
/etc/conf/bin/idtune SHMMAX value
这里 value 是你想设置的以字节记的新值。设置完SHMMAX 后,重建内核
/etc/conf/bin/idbuild -B
然后重起。
BSD/OS
共享内存. 缺省时是只支持 4 MB 的共享内存。请记住共享内存是不能分页的;它是锁在 RAM 里面的。要增加你的系统支持的共享缓冲区数目,向你的内核配置文件里增加下面的行:
options "SHMALL=8192" options "SHMMAX=\(SHMALL*PAGE_SIZE\)"
SHMALL 以 4KB 页为单位计算,所以 1024 页面代表 4 M 共享内存。 所以上面的东西把共享内存区域增加到 32 MB。 对于运行 4.3 或者更新版本的人,你可能需要增大 KERNEL_VIRTUAL_MB ,超过缺省的 248 。 做完上面的修改之后,然后编译内核并重起。
对于运行 4.0 或者更早的版本的, 请用 bpatch 找出当前内核的 sysptsize 值。它是启动的时候动态计算的。
$ bpatch -r sysptsize 0x9 = 9
然后,把 SYSPTSIZE 修改为在内核配置文件里的一个硬代码值。用 bpatch 算出来的值,并且为你需要的每个额外的 4 MB 共享内存再加 1。
options "SYSPTSIZE=16"
sysptsize 不能用 sysctl 修改。
信号灯. 你可能还需要增加信号灯的数量;系统缺省的总数 60 只能允许大概 50 个 PostgreSQL 连接。在内核配置文件里设置你需要的值,比如:
options "SEMMNI=40" options "SEMMNS=240"
缺省设置只适合于很小的安装(比如,缺省 SHMMAX 是 32 MB)。我们可以用 sysctl 或者 loader 接口来修改。下面的参数可以用 sysctl 设置:
$ sysctl -w kern.ipc.shmall=32768 $ sysctl -w kern.ipc.shmmax=134217728 $ sysctl -w kern.ipc.semmap=256
要想让这些设置重启后有效,修改 /etc/sysctl.conf 。
如果用 sysctl ,那么剩下的信号灯设置是只读的,但是信号灯可以在启动的时候,在 loader 提示符下设置:
(loader) set kern.ipc.semmni=256 (loader) set kern.ipc.semmns=512 (loader) set kern.ipc.semmnu=256
类似的,这些东西可以在 /boot/loader.conf 中保存,以便重启之后依然有效。
你可能还想配置内核,让把共享内存装载到 RAM 里,避免他们被交换到交换分区中。这些可以通过使用 sysctl 设置kern.ipc.shm_use_phys 来实现。
在 4.0 之前的 FreeBSD 版本类似 NetBSD 和 OpenBSD (见下文)。
编译内核时需要把选项 SYSVSHM 和 SYSVSEM 打开。(缺省是打开的。)共享内存的最大尺寸是由选项SHMMAXPGS (以页计)。下面显示了一个如何设置这些参数的例子(OpenBSD 使用的是 option ):
options SYSVSHM options SHMMAXPGS=4096 options SHMSEG=256 options SYSVSEM options SEMMNI=256 options SEMMNS=512 options SEMMNU=256 options SEMMAP=256
你可能原意使用 sysctl 设置将共享内存锁在 RAM 中以避免它们被交换出去,我们可以用 sysctl 设置kern.ipc.shm_use_phys 来实现这个目的。
缺省设置看来对普通安装是足够的了。 在 HP-UX 10,SEMMNS 的出厂缺省是 128,可能对大的数据库节点来说太小了。
IPC 可以在 System Administration Manager(系统管理器) (SAM )下面的 Kernel Configuration ->Configurable Parameters 配置。你配置完了以后敲 Create A New Kernel 选项。