/etc/security/limits 关于 stack 的限制有两个参数,分别是:
* stack - soft stack segment size in blocks
* stack_hard - hard stack segment size in blocks
其中 stack 是软限制(当前限制值),而 stack_hard 是硬限制(最高可设置的软限制值)。 stack_hard 取值一般直接采用系统默认值。
本案例中,客户误将 stack_hard 设置为 -1 ,造成在本地启动 sqlplus 进程时,系统 CPU 消耗显著上升,系统整体性能受到了影响。
在stack的硬限制为-1的情况下 , 如果64 位进程把 stack 的软限制先通过 setrlimit 先改小 , 再改成 -1/RLIM_INFINITY , 就会触发系统分配 大量 stack segments ( 4096 个)以满足 stack size limit 扩充的需求。如果 stack 软限制始终保持为默认的 -1 , 则不会触发(系统默认初始分配 16 个 stack segments ,用完再分配新的 segments )。
从最近的一个客户案例看, oracle 11gR2 sqlplus 会调用 setrlimit 先改小 stack size( 把 soft limit 设置成 32MB) , 再改大 stack size( 取值为当前环境 ulimit -s 的实际值,在案例的环境中为 -1) , 正好符合了上述模式,因此触发了大量 stack segments 分配。作为对比, Oracle 19c 不存在此问题,即使当前系统环境 stack_hard=-1 也不会触发大量分配 stack segments 问题。这样 11gR2 在启动、退出 sqlplus 的过程耗时将会显著增加( fork 时分配 segments , exit 时销毁 segments );如果正好有大量 sqlplus 进程创建、退出,可能造成极高的 sys CPU 消耗,影响系统效率。
如下是一个 11gR2 sqlplus 的 truss 输出片段(第二个参数是指针,使用 dbx 跟踪可以观察到指针指向的具体值,有兴趣可以自行尝试):
$ truss -t appgetrlimit,appsetrlimit sqlplus "/as sysdba"
appgetrlimit(3, 0x0FFFFFFFFFFFE830) = 0
appgetrlimit(3, 0x0FFFFFFFFFFFE5D0) = 0
appsetrlimit(3, 0x0FFFFFFFFFFFE5D0) = 0 // 参考 /usr/include/sys/resource.h, 第一个参数值 3 代表 RLIMIT_STACK ,也即设置 stack size.
appgetrlimit(3, 0x0FFFFFFFFFFFE830) = 0
appgetrlimit(3, 0x0FFFFFFFFFFFE820) = 0
appsetrlimit(3, 0x0FFFFFFFFFFFE820) = 0
SQL*Plus: Release 11.2.0.4.0 Production on Wed Jul 12 11:54:39 2017
Copyright (c) 1982, 2013, Oracle. All rights reserved.
系统配置参数stack_hard不应当设置为-1。 通常我们只要求对 oracle 用户设置 stack 为 -1( 软限制 ) ,而 stack_hard 硬限制默认为 8388608 blocks , 也就是 4GB ,即 16 个 stack segments ( 每个 segment 大小为 256MB) 。
Stack segments 主要存储调用栈信息以及临时变量等等。 16 个 segments 对于 stack 来说已经绰绰有余,即使是负载很重的 64 位进程,一般也最多只用到几个段。因为通常主要的数据都集中在 shared memory segments (比如 SGA )、 data segments (比如 PGA )、和 client segments (比如访问的文件)。
Oracle 安装手册说明了只要求 stack=-1 ( Soft Limit ),并没有要求设置 stack_hard 为 -1 (Hard Limit).
对于安装 Oracle 11gR2 的 AIX 环境, 建议检查 /etc/security/limits 里,是否误添加了 “ stack _hard =-1 ”的设置 ,如果存在,删除即可,后续用户重新登录时即可生效。
说明:
PS: 根据某客户反馈, Oracle 10g 也不存在此问题。预计此 bug 仅限 Oracle11gR2 。用户可以根据附录一中的 dbx 方法来确认您的环境下 sqlplus 是否存在此问题。
【 truss 数据】
如下是一个 truss 输出片段(第二个参数是指针,使用 dbx 跟踪可以观察到指针指向的具体值,有兴趣可以自行尝试):
$ truss -t appgetrlimit,appsetrlimit sqlplus "/as sysdba"
appgetrlimit(3, 0x0FFFFFFFFFFFE830) = 0
appgetrlimit(3, 0x0FFFFFFFFFFFE5D0) = 0
appsetrlimit(3, 0x0FFFFFFFFFFFE5D0) = 0 // 参考 /usr/include/sys/resource.h, 第一个参数值 3 代表 RLIMIT_STACK ,也即设置 stack size.
appgetrlimit(3, 0x0FFFFFFFFFFFE830) = 0
appgetrlimit(3, 0x0FFFFFFFFFFFE820) = 0
appsetrlimit(3, 0x0FFFFFFFFFFFE820) = 0
而在 Oracle 10g 的版本里面是没有调用setrlimit方法的,所以即使在 10g 的环境中设置了 stack_hard 为 -1 也不会触发问题。
正常情况与异常情况的 truss 对比
【 dbx 数据】
对 19c 的跟踪, 19c 的 sqlplus 不会调用 appsetrlimit 修改 stack 限制(而是直接使用默认值):
对 11g 的跟踪如下, 11g 的 sqlplus 会调用两次 appsetrlimit 修改 stack 限制,第一次设置为 32MB ,第二次设置为 unlimited ,触发段空间分配:
$ dbx /oracle/db/bin/sqlplus
Type 'help' for help.
reading symbolic information ...warning: no source compiled with -g
(dbx) listi appgetrlimit
0x900000000206290 (appgetrlimit) e9822c68 ld r12,0x2c68(r2)
0x900000000206294 (appgetrlimit+0x4) f8410028 std r2,0x28(r1)
0x900000000206298 (appgetrlimit+0x8) e80c0000 ld r0,0x0(r12)
0x90000000020629c (appgetrlimit+0xc) e84c0008 ld r2,0x8(r12)
0x9000000002062a0 (appgetrlimit+0x10) 7c0903a6 mtctr r0
0x9000000002062a4 (appgetrlimit+0x14) 4e800420 bctr
0x9000000002062a8 (appgetrlimit+0x18) 00000000 Invalid opcode.
0x9000000002062ac (appgetrlimit+0x1c) 000ca000 Invalid opcode.
0x9000000002062b0 (appgetrlimit+0x20) 00000000 Invalid opcode.
0x9000000002062b4 (appgetrlimit+0x24) 00000018 Invalid opcode.
(dbx) stop in appsetrlimit
[1] stop in appsetrlimit
(dbx) run "/as sysdba"
[1] stopped in appsetrlimit at 0x900000000206268 ($t1)
0x900000000206268 (appsetrlimit) e9822c60 ld r12,0x2c60(r2)
(dbx) where
appsetrlimit() at 0x900000000206268
setrlimit(??, ??) at 0x900000000206050
sskgm_set_stack_limit(??, ??, ??) at 0x100103e2c
sskgminit(??, ??) at 0x100103b5c
skgminit(??, ??, ??, ??) at 0x1000f98a4
kpuiniPG(??) at 0x10009a9f4
kpuinit0(??, ??, ??, ??, ??, ??, ??, ??) at 0x10009bf40
kpuenvcr(0x900000000000980, 0x2700000026, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0) at 0x10009a670
OCIEnvCreate(??, ??, ??, ??, ??, ??, ??, ??) at 0x1000866bc
afioci(??, ??, ??) at 0x100085884
aficntini(??) at 0x101cc83a0
afidrv(??, ??, ??, ??) at 0x10005dce0
main(??, ??) at 0x100000688
(dbx) registers
$r0:0x0000000100103e30 $stkp:0x0fffffffffffe4e0 $toc:0x09001000a01e94d0
$r3:0x0000000000000003 $r4:0x0fffffffffffe5e0 $r5:0x7fffffffffffffff
$r6:0x800000000000f032 $r7:0x0000000000003b60 $r8:0x0000000000000000
$r9:0xf1000a01508b7400 $r10:0x0000000000000000 $r11:0xf00000002ff47600
$r12:0x09001000a01e2350 $r13:0x00000001101f00e0 $r14:0x00000001102be2b0
$r15:0x0000000101f050e8 $r16:0x0000000101f05150 $r17:0x0000000000000000
$r18:0x00000001102be9d0 $r19:0x00000001102be420 $r20:0x0000000000000000
$r21:0x0000000000000000 $r22:0x0000000000000000 $r23:0x0000000000000000
$r24:0x0000000000000000 $r25:0x0000000000000000 $r26:0x0000000000000000
$r27:0x0000000101d62c58 $r28:0x0000000002000000 $r29:0x0fffffffffffe990
$r30:0x0fffffffffffe968 $r31:0x0000000000000000
$iar:0x0900000000206268 $msr:0xa00000000000d032 $cr:0x22200228
$link:0x0900000000206054 $ctr:0x0900000000206040 $xer:0x00000000
Condition status = 0:e 1:e 2:e 5:e 6:e 7:l
[unset $noflregs to view floating point registers]
[unset $novregs to view vector registers]
[unset $novsregs to view vector scalar registers]
in appsetrlimit at 0x900000000206268 ($t1)
0x900000000206268 (appsetrlimit) e9822c60 ld r12,0x2c60(r2)
(dbx) 0x0fffffffffffe5e0/16x
0x0fffffffffffe5e0: 0000 0000 0200 0000 7fff ffff ffff ffff
0x0fffffffffffe5f0: 0fff ffff ffff e670 0000 0000 0000 0000
(dbx) cont
[1] stopped in appsetrlimit at 0x900000000206268 ($t1)
0x900000000206268 (appsetrlimit) e9822c60 ld r12,0x2c60(r2)
(dbx) registers
$r0:0x0000000100103e30 $stkp:0x0fffffffffffe730 $toc:0x09001000a01e94d0
$r3:0x0000000000000003 $r4:0x0fffffffffffe830 $r5:0x7fffffffffffffff
$r6:0x800000000000f032 $r7:0x0000000000003b60 $r8:0x0000000000000000
$r9:0xf1000a01508b7400 $r10:0x0000000000000000 $r11:0xf00000002ff47600
$r12:0x09001000a01e2350 $r13:0x00000001101f00e0 $r14:0x00000001102be2b0
$r15:0x0000000101f050e8 $r16:0x0000000101f05150 $r17:0x0000000000000000
$r18:0x00000001102be9d0 $r19:0x00000001102be420 $r20:0x0000000000000000
$r21:0x0000000000000000 $r22:0x0000000000000000 $r23:0x0000000000000000
$r24:0x0000000000000000 $r25:0x0000000000000000 $r26:0x0000000000000000
$r27:0x0000000101d62c58 $r28:0x7fffffffffffffff $r29:0x0000000000000000
$r30:0x0000000000000000 $r31:0x0000000000000000
$iar:0x0900000000206268 $msr:0xa00000000000d032 $cr:0x22200228
$link:0x0900000000206054 $ctr:0x0900000000206040 $xer:0x00000000
Condition status = 0:e 1:e 2:e 5:e 6:e 7:l
[unset $noflregs to view floating point registers]
[unset $novregs to view vector registers]
[unset $novsregs to view vector scalar registers]
in appsetrlimit at 0x900000000206268 ($t1)
0x900000000206268 (appsetrlimit) e9822c60 ld r12,0x2c60(r2)
(dbx) where
appsetrlimit() at 0x900000000206268
setrlimit(??, ??) at 0x900000000206050
sskgm_set_stack_limit(??, ??, ??) at 0x100103e2c
skgm_set_stack_limit(??, ??, ??) at 0x1000f9f4c
kpuiniPG(??) at 0x10009aa4c
kpuinit0(??, ??, ??, ??, ??, ??, ??, ??) at 0x10009bf40
kpuenvcr(0x900000000000980, 0x2700000026, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0) at 0x10009a670
OCIEnvCreate(??, ??, ??, ??, ??, ??, ??, ??) at 0x1000866bc
afioci(??, ??, ??) at 0x100085884
aficntini(??) at 0x101cc83a0
afidrv(??, ??, ??, ??) at 0x10005dce0
main(??, ??) at 0x100000688
(dbx) 0x0fffffffffffe830/16x
0x0fffffffffffe830: 7fff ffff ffff ffff 7fff ffff ffff ffff
0x0fffffffffffe840: 0000 0000 0200 0000 0000 0000 0000 0000
(dbx) cont
SQL*Plus: Release 11.2.0.4.0 Production on Wed Jul 12 12:23:15 2017
Copyright (c) 1982, 2013, Oracle. All rights reserved.
Connected to:
Oracle Database 11g Enterprise Edition Release 11.2.0.4.0 - 64bit Production
With the Partitioning and Automatic Storage Management options
SQL> quit
Disconnected from Oracle Database 11g Enterprise Edition Release 11.2.0.4.0 - 64bit Production
With the Partitioning and Automatic Storage Management options
execution completed
如果觉得我的文章对您有用,请点赞。您的支持将鼓励我继续创作!
赞4
添加新评论0 条评论