• ORA-1034 ORA-27102


    ORA-1034 ORA-27102

    ORA-1034 ORA-27102

    没有足够的空闲内存. 这个问题很难分析。因为有时候,我们所依赖的操作系统命令,其实是在逗我们玩儿。 下面是我的一欠遍体鳞伤的经历,不堪回首呀。

    1 现象

    客户反馈数据库无法连接,报错信息如下:

    
    SQL*Plus: Release 12.2.0.1.0 Production on Thu May 21 20:47:50 2020
    
    Copyright (c) 1982, 2016, Oracle.  All rights reserved.
    
    ERROR:
    ORA-01034: ORACLE not available
    ORA-27102: out of memory
    Linux-x86_64 Error: 12: Cannot allocate memory
    Additional information: 2731
    Additional information: 557064
    Additional information: 1744830464
    Process ID: 0
    Session ID: 0 Serial number: 0
    
    
    Enter user-name:
    

    2 分析

    连接的时候无内存分配。。数据库连接的时候,都哪里需要内存呢?操作系统进程和oracle pga,但是后者所需很少. 先看物理内存吧。

    [root@bossdb1 ~]# free -m
                  total        used        free      shared  buff/cache   available
    Mem:          64213        6219       25718       31115       32275       25987
    Swap:         32191           0       32191
    

    有25G 的空闲内存,哎哟,看来不是内存的问题,。难道是内核参数设置不正确或者分给Oracle 的内存用光了?如果是后者那太可怕了。

    !就是从这儿开始,我在鬼打墙里转了两天!

    2.1 内核参数

    查看内核参数和用户限制吧。

    # 查看用户最大允许锁定内存
    [grid@bossdb1 ~]$ ulimit -m
    unlimited
    
    [oracle@bossdb2 ~]$ ulimit -m
    unlimited
    [grid@bossdb2 ~]$
    

    都没有限制。 查看shmmax 和shmall:

    [root@bossdb1 69431]# sysctl -a |grep kernel.shm
    kernel.shm_next_id = -1
    kernel.shm_rmid_forced = 0
    kernel.shmall = 16438528
    kernel.shmmax = 67332210688
    kernel.shmmni = 4096
    ........
    

    从上面查看的物理总内存为64G . 这里shmmax=67332210688/1024/1024/1024 = 62G shmall=16438528*4096/1024/1024/1024 = 62G

    从这里看,也没有问题。

    难道真的数据库把内存用光了?

    2.2 数据库内存使用情况

    • 内存上限

        show parameter memory_max_target
      
      NAME                                 TYPE                             VALUE
      ------------------------------------ -------------------------------- ------------------------------
      memory_max_target                    big integer                      50048M
      
    • SGA

        select inst_id,sum(bytes)/(1024*1024*1024) from gv$sgainfo
       where name not in ('Granule Size','Maximum SGA Size','Startup overhead in Shared Pool','Free SGA Memory Available') group by inst_id
      
         INST_ID SUM(BYTES)/(1024*1024*1024)
      ---------- ---------------------------
               1                  26.2499972
               2                  19.7499972
      
    • PGA

        select inst_id,value/(1024*1024*1024) from gv$pgastat where name='total PGA allocated';
      
         INST_ID VALUE/(1024*1024*1024)
      ---------- ----------------------
               2             2.93612671
               1              4.7712841
      

      以上内存使用总量:

      节点 内存使用量
      1 26.25+4.77 = 31.02
      2 19.75+2.94 = 22.69

      两个节点内存使用远没有达到上限呢。

      这是什么鬼??物理内存充足,Oracle 内存没有达到上限。怎么就无法分配内存了呢?难道是Oracle 12C BUG ?

      MOS 查起来。。。发现没有BUG. 而且遇到这种情况的都是之前检查的内容。难道是进程数达到上限了?不对。达到进程数上限不是这个错误。

      生无可恋了。。。。无心睡眠。。这是哪儿的问题。。 正好赶上客户要做变更。。晚上要停业务。。

      重启是万能的法宝。晚上一起重启了吧。第二天,一个白天都灰常顺利。。开心下班。。以为这次就这么过去了。 可是刚到家。同事发来消息: 数据库又不能连了,跟昨天一样的错误。

      我的以内那是一万匹草泥马奔腾而过…………….

      从头开始。

    • 物理内存

      接着查看物理内存使用情况:

                    total        used        free      shared  buff/cache   available
      Mem:          64213        7209       33239       20670       23764       35384
      Swap:         32191           0       32191
      

      并没有太大的变化 。

      top - 23:51:30 up 1 day, 23:35,  4 users,  load average: 1.99, 1.97, 2.06
      Tasks: 699 total,   2 running, 697 sleeping,   0 stopped,   0 zombie
      %Cpu(s):  6.4 us,  2.0 sy,  0.0 ni, 85.6 id,  6.0 wa,  0.0 hi,  0.0 si,  0.0 st
      KiB Mem : 65754708 total, 34170344 free,  7248336 used, 24336028 buff/cache
      KiB Swap: 32964604 total, 32964604 free,        0 used. 36368028 avail Mem
      

      并没有问题。虽然有预期,但是还是有点失望。随便看看吧。现在数据库有多少进程呀?

    3 解决

    3.1 第一次尝试

    select inst_id,machine,program,count(*) from gv$session group by inst_id,machine,program order by 4;
    
       INST_ID MACHINE      PROGRAM                        COUNT(*)
    ---------- ------------ ---------------------------- ----------
             2 bossdb2      oracle@bossdb2 (PING)                 1
    .............
             2 boss-ei1     JDBC Thin Client                     13
             1 ilogmaster   shiyi@ilogmaster (TNS V1-V3)         23
             1 KMGDCCWeb1   JDBC Thin Client                     24
             2 ipcc-hp-app  JDBC Thin Client                    522
             1 ipcc-hp-app  JDBC Thin Client                    887
    

    我个去,这是什么情况,一台应用服务器怎么连到数据库里有1400+ 进程。。都是活动的?

    select inst_id,status,count(*) from gv$session where machine='ipcc-hp-app' group by inst_id,status;
    
       INST_ID STATUS     COUNT(*)
    ---------- -------- ----------
             1 INACTIVE        862
             2 INACTIVE        522
             1 ACTIVE            1
    

    都是不活动的。这些进程,占用了多少数据库内存,又占用了多少操作系统的物理内存?前者可能不大,但是后者肯定是有些恐怖的。

    这些进程为什么不会退出呢?就算应用里没有退出机制,在数据库里也有空闲连接的配置呀:

    col limit for a10
    col resource_name for a15
    col profile for a20
    select profile,resource_name,limit from dba_profiles where resource_name = 'IDLE_TIME';
    
    PROFILE              RESOURCE_NAME   LIMIT
    -------------------- --------------- ----------
    DEFAULT              IDLE_TIME       UNLIMITED
    

    居然是个Unlimited.

    此刻我内心,其实已经倾向于是这些进程搞的鬼了。。。先把idle_time 限制起来吧。

    alter profile default limit idle_time 180;
    

    限制180,也就是3个小时,已经很长了。等一会儿,看看,果然pmon 已经清理超时进程了。

    ........
    KILL SESSION for sid=(2973, 57359):
    Reason = profile limit idle_time
    Mode = KILL SOFT -/-/-
    Requestor = PMON (orapid = 2, ospid = 33310, inst = 1)
    Owner = Process: USER (orapid = 815, ospid = 95705)
    Result = ORA-0
    .........
    

    现在数据库也可以正常连接。那么基本可以肯定是这些进程搞的鬼。

    但是,我心里仍有不甘。真的是这些进程搞得鬼么?还是只是凑巧,其他地方的问题也恢复了。

    观察两天,之前重复出现的问题没有再出现。那么基本肯定是这些进程引起的问题。

    研究很久,目前也没有找到方法统计进程占用的真实的物理内存,哎。

    本以为这次已经解决了。但是三天后的傍晚再一次报错。

    3.2 第二次尝试

    现象与之前一样,但是实在是没办法了。按照往常的经验,分配给 Oracle 的内存是物理内存的80%。 64*0.8 是51g+ ,我分配给ORACLE 50G(memory_target,memory_max_size). 但是这次发现buffer/cache 占用非常高几乎达到了我分配给oracle 的内存。

    [oracle@bossdb1 ~]$ free -m
                  total        used        free      shared  buff/cache   available
    Mem:          64213       13147        1248       32566       49817       17399
    Swap:         32191           0       32191
    

    按原理来讲,Linux 在物理内存不足的情况下,会自动清理buffer/cache 中。但系统并没有清理,关于 在5、6版本中控制尽快清理 buffer/cache 的内核参数vm.extra_free_kbytes 在CentOS7中也被去除了。 尝试设置此参数时会有如下提示:

    sysctl -w vm.extra_free_kbytes=10240000
    sysctl: cannot stat /proc/sys/vm/extra_free_kbytes: No such file or directory
    

    没有办法了,黔驴技穷的我,只有两个操作可以做了,一是降低Oracle 内存分配,另一个就是定时清理cache.

    # 降低Oracle 内存分配。将原来的50G 改为30G .
    alter system set memory_target=30G scope=spfile sid='*';
    startup force
    

    做定时任务,每小时清理一次。 编写脚本:

    cat >> /root/scripts/clear_buffer.sh<<EOF
    sync;sync;sync;
    sleep 20
    echo 3 > /proc/sys/vm/drop_caches
    EOF
    编写定时任务,crontab -e 编写,crontab -l 查看,内容如下:
    
    0   *    *    *    *    sh /root/scripts/clear_buffer.sh
    

    设置系统参数 vm.vfs_cache_pressure=500,以加速清理vfs缓存。

    sysctl -w vm.vfs_cache_pressure=500
    cat >> /etc/sysctl.conf<<EOF
    vm.vfs_cache_pressure = 500
    EOF
    

    操作完成后,内存使用情况如下:

    节点1:
    [oracle@bossdb1 ~]$ free -m
                  total        used        free      shared  buff/cache   available
    Mem:          64213        5170       37881       20195       21160       37969
    Swap:         32191           0       32191
    节点2:
    [oracle@bossdb2 ~]$ free -m
                  total        used        free      shared  buff/cache   available
    Mem:          64213        4215       32670       19278       27328       39781
    Swap:         32191           0       32191
    

    次日:

    [root@bossdb1 ~]# free -m
                  total        used        free      shared  buff/cache   available
    Mem:          64213       10061       32486       20587       21665       32459
    Swap:         32191           0       32191
    [root@bossdb2 scripts]# free -m
                  total        used        free      shared  buff/cache   available
    Mem:          64213        8660       33739       20830       21812       33652
    Swap:         32191           0       32191
    

    观察一星期后,问题不再出现。

    4 总结

    在第一次尝试解决的时候,其实我没有注意到,oracle(sga+pga)+ 操作系统中的buffer/cache 其实已经接近满内存了。

    对于CentOS 7.6 没有了控制清除buffer/cache的内核参数,所以只有通过crontab 定时任务清理。否则会出现由于 buffer/cache不释放将内存耗光的情况。

    Author: halberd.lee

    Created: 2020-05-29 Fri 14:17

    Validate

  • 相关阅读:
    Vue 实现前进刷新,后退不刷新的效果
    chrome浏览器的跨域设置——包括版本49前后两种设置
    Promise.all和Promise.race区别,和使用场景
    滚动条默认最底部
    使用react进行父子组件传值
    java 数组基础学习(一维二维数组)
    react项目 使用echarts
    Python的hasattr() getattr() setattr() 函数使用方法详解
    【线性判别】Fisher线性判别(转)
    【semantic segmentation】Pyramid Scene Parsing Network(转)
  • 原文地址:https://www.cnblogs.com/halberd-lee/p/12943666.html
Copyright © 2020-2023  润新知