1. 程式人生 > >診斷並解決 ORA-4030 錯誤 (Doc ID 1548826.1)

診斷並解決 ORA-4030 錯誤 (Doc ID 1548826.1)

area 2gb version trace note master cached detach ogr

適用於:

Oracle Database - Enterprise Edition - 版本號 8.1.7.4 和更高版本號

本文檔所含信息適用於全部平臺

用途

怎樣診斷 ORA-4030 錯誤

排錯步驟

診斷並解決 ORA-4030 錯誤

ORA-4030 意味著什麽?

你可能在日誌文件裏或者屏幕上看到這個錯誤: ORA-04030 ‘out of process memory when trying to allocate %s bytes (%s,%s)‘

該錯誤意味著 Oracle Server 進程無法從操作系統分配很多其它內存。該內存由 PGA(Program Global Area)組成。其內容取決於server配置。

對於專用的server進程,內存包括堆棧以及用於保存用戶會話數據、遊標信息和排序區的 UGA(User Global Area)。

在多線程配置中(共享server)。UGA 被分配在 SGA(System Global Area)中,所以在這樣的配置下 UGA 不是造成 ORA-4030 錯誤的原因。

因此。ORA-4030 表示進程須要很多其它內存(堆棧 UGA 或 PGA)來運行其任務。

是什麽導致了該錯誤?

因為發生了這個錯誤,您因此無法從操作系統分配內存。

這個錯誤可能是進程本身導致的,比如進程須要過多的內存。或者一些其它原因導致操作系統內存被耗盡。比如 SGA 太大或系統虛擬內存(物理內存 + 交換空間)中要容納的進程過多。很多操作系統會對單個進程可以獲取的內存量加以限制。以便自我保護。所以我們就會有下列問題:

問題:

  • 是否仍然有足夠的可用內存?

  • 是否設置了操作系統限制?

  • 是否設置了 Oracle 限制?

  • 哪個進程須要的內存過多?

  • 怎樣收集有關進程實際正在運行的任務的信息?

以下我們將討論這些內容。

其它主題:

  • 有關避免此錯誤的一般建議

是否仍然有足夠的可用內存?

要回答這個問題,我們須要使用操作系統特定的工具來檢查內存使用情況。

  1. OpenVMS 系統:show memory 會提供關於物理內存和頁面文件使用情況的信息:

    Physical Memory Usage (pages): Total Free In Use Modified
    Main Memory (256.00Mb) 32768 24849 7500 419

    .....

    Paging File Usage (blocks): Free Reservable Total
    DISK$BOBBIEAXPSYS:[SYS0.SYSEXE]SWAPFILE.SYS 30720 30720 39936
    DISK$BOBBIEAXPSYS:[SYS0.SYSEXE]PAGEFILE.SYS 226160 201088 249984
    DISK$BOBBIE_USER3:[SYS0.PAGEFILE]PAGEFILE.SYS 462224 405296 499968

    作為一般準則。頁面文件裏的可用空間總和應不低於整個空間總和的一半。
    交換文件應差點兒不使用,可用空間的大小應大致等於總空間的大小。

  2. Windows 系統:在“任務管理器”的性能選項卡中檢查內存使用情況。

  3. Unix 系統:每種 unix 系統通常都有自己的工具來檢查系統上的全局內存使用情況,如 top、vmstat……而且在不同的 OS 上,內存管理的運作方式各不同樣。

    • top 一般會顯示物理內存和交換空間的統計信息

    • swapon -s 顯示交換空間使用情況

    • vmstat 顯示可用物理內存

Linux 上的 top 輸出演示樣例:

top - 10:17:09 up 1:27, 4 users, load average: 0.07, 0.12, 0.05
Tasks: 110 total, 4 running, 105 sleeping, 0 stopped, 1 zombie
Cpu(s): 0.3% user, 1.6% system, 0.0% nice, 98.0% idle
Mem: 1033012k total, 452520k used, 580492k free, 59440k buffers
Swap: 1052248k total, 0k used, 1052248k free, 169192k cached
.....

假設有足夠的內存可用,請檢查操作系統是否存在強制限制。

假設內存已被耗盡,我們就須要找出內存被用到了哪些地方。

是否設置了操作系統限制?

假設似乎仍剩余大量的虛擬內存。那麽有可能是我們須要使用的內存量是不被同意的。以下的步驟能夠用來檢查由操作系統實施的限制。

  1. OpenVMS 系統:若要檢查您能夠使用的物理內存量,請使用授權工具來檢查 working set 配額和頁面文件配額。

    請參閱 OpenVMS 部分。了解使用了哪些配額以及怎樣改動配額。依據進程類型以及啟動的方式,其所用的配額可能不是 Oracle中的那部分配額。

    show process/id=/quota 會顯示某個進程還剩余多少配額。

    UAF> show oracle7

    Username: ORACLE7 Owner: Oracle7 DBA
    Account: SUPPORT UIC: [200,2] ([SUPPORT,ORACLE7])
    CLI: DCL Tables: DCLTABLES
    Default: DISK$BOBBIE_USER1:[ORACLE7]
    LGICMD: LOGIN
    Flags:
    Primary days: Mon Tue Wed Thu Fri
    Secondary days: Sat Sun
    No access restrictions
    Expiration: (none) Pwdminimum: 6 Login Fails: 0
    Pwdlifetime: (none) Pwdchange: 3-DEC-1997 15:38
    Last Login: 27-MAY-2003 14:54 (interactive), 26-MAY-2003 16:15 (non-interactive)
    Maxjobs: 0 Fillm: 1200 Bytlm: 180000
    Maxacctjobs: 0 Shrfillm: 0 Pbytlm: 0
    Maxdetach: 0 BIOlm: 500 JTquota: 8192
    Prclm: 20 DIOlm: 500 WSdef: 2500
    Prio: 4 ASTlm: 4000 WSquo: 4096
    Queprio: 0 TQElm: 4000 WSextent: 30000
    CPU: (none) Enqlm: 18000 Pgflquo: 750000
    Authorized Privileges: .....

    $ sho proc/id=20200139/quota

    24-JUN-2003 12:30:54.39 User: ORACLE7 Process ID: 20200139
    Node: BOBBIE Process name: "ORA_BOB901_PMON"

    Process Quotas:
    Account name: SUPPORT
    CPU limit: Infinite Direct I/O limit: 100
    Buffered I/O byte count quota: 9994816 Buffered I/O limit: 100
    Timer queue entry quota: 99 Open file quota: 29997
    Paging file quota: 145968 Subprocess quota: 10
    Default page fault cluster: 64 AST quota: 496
    Enqueue quota: 49995 Shared file limit: 0
    Max detached processes: 0 Max active jobs:

  2. Windows 系統:在 Microsoft Windows 操作系統中,Oracle 各個進程是在一個進程中以多線程實施的。

    對於 32 位的系統。可尋址的內存量為 2Gb(包含堆棧、PGA 和 SGA)。此限制能夠添加到 3Gb 或更高。有關很多其它信息,請參閱“Oracle Database and the Windows NT memory architecture, Technical Bulletin”。

    對於 64 位的系統這個限制就高多了。Oracle 進程使用的總內存(不包含進程堆棧和代碼)可通過此查詢進行確定。

  3. Unix 系統:使用 limit/ulimit shell builtin 命令。請註意,unlimited 的不一定意味著不受限制,實際也可能是基於歷史原因的限制。比如 2Gb。推薦基於真實須要的量進行設置:

    Linux 輸出演示樣例:

    [email protected]:~> ulimit -a

    core file size (blocks, -c) 0
    data seg size (kbytes, -d) unlimited
    file size (blocks, -f) unlimited
    max locked memory (kbytes, -l) unlimited
    max memory size (kbytes, -m) unlimited
    open files (-n) 1024
    pipe size (512 bytes, -p) 8
    stack size (kbytes, -s) unlimited
    cpu time (seconds, -t) unlimited
    max user processes (-u) 7168
    virtual memory (kbytes, -v) unlimited


    有的問題可能是由於限制設置得過低造成的,所以須要進行對應的添加。也有的問題可能是由於我們須要使用的太多造成的。



    請註意:其它 OS 參數設置(比如 maxuproc)可能會導致問題

    比如,”ORA-4030 (QERHJ HASH-JOI,KLLCQAS:KLLSLTBA)”
    Status: 92,Closed, Not a Bug

    ***來自於 bug - "Increased MAXUPROC from 1000 to 2000, restarted the listener and ORA-4030 errors were resolved"

是否設置了 Oracle 限制?

從 Oracle Version 9i 開始我們引入了參數 PGA_AGGREGATE_TARGET。該參數嘗試限制一個實例能夠分配的 PGA 總量。“Automatic PGA Memory Managment”部分提供了關於此問題的很多其它信息。下面查詢可用於查找分配給全部會話的 PGA 區的內存總量:

SQL> select

sum(value)/1024/1024 Mb

from

v$sesstat s, v$statname n

where

n.STATISTIC# = s.STATISTIC# and

name = ‘session pga memory‘;

哪個進程須要的內存過多?

一些操作會須要大量的進程內存,比如大型的 PL/SQL 表或大量的排序操作。在這些情況下。在出現錯誤 ORA-4030 之前。進程將會執行一段時間,所以我們有希望在這段時間內能找出內存分配的位置和原因。

您能夠使用下面查詢來查找從 Oracle 角度看來所用於 Oracle 進程的 PGA 和 UGA 大小。

SQL> col name format a30

SQL> select

sid,name,value

from

v$statname n,v$sesstat s

where

n.STATISTIC# = s.STATISTIC# and

name like ‘session%memory%‘

order by 3 asc;

此查詢會顯示列表中最占內存的進程。

通常。從操作系統的角度來確認進程內存使用情況。是一個好辦法。

畢竟,使用過多內存的不一定是 Oracle Server 進程。

通常,對於server進程而言。Oracle 和操作系統之間基本都能夠就內存的使用情況達成一致。通過下面命令,您能夠查找操作系統中進程的內存使用情況。

  1. OpenVMS 系統:show system 將顯示關於進程和資源的整體使用情況。

    頻繁調用頁面失敗的進程一般會使用大量虛擬內存。“Pages”列指示物理頁的使用情況。

    show process/continious 命令顯示物理(工作集)和虛擬內存的使用情況。


    $ show system/pag OpenVMS V7.2-1 on node BOBBIE 13-JUN-2003 09:56:30.44 Uptime 17 18:58:18
    Pid Process Name State Pri I/O CPU Page flts Pages
    20200101 SWAPPER HIB 16 0 0 00:00:02.45 0 0
    20200106 CLUSTER_SERVER HIB 13 104 0 00:00:00.03 87 104
    20200107 CONFIGURE HIB 10 21 0 00:00:00.06 77 17



    $ sho process/id=xxx/cont:
    Process AROELANT 10:00:53
    State CUR Working set 131
    Cur/base priority 6/4 Virtual pages 11714
    Current PC 800D9B28 CPU time 0 00:00:01.28
    Current PSL 00000003 Direct I/O 178
    Current user SP 7A5227F0 Buffered I/O 962
    PID 20200469 Page faults 1312
    UIC [SUPPORT,AROELANT] Event flags C0000003
    C0000000

  2. Windows 系統:在 Microsoft windows 系統中, Oracle 是通過在單個進程中使用多個線程來實施的。直到如今,尚未找到能夠查看每一個線程的內存使用情況的方法。可是,我們能夠檢查 Oracle 和操作系統是否就 Oracle 所使用的內存達成一致。從操作系統的角度看,我們能夠使用任務管理器。單擊查看button並選擇選擇列(S)...,確保已選中虛擬內存大小(V)

    oracle.exe 的虛擬內存大小 列中顯示的大小應與 SGA、總 PGA 內存以及進程堆棧和代碼大小的總和同樣。下面查詢可用於獲取 Oracle 所查看的內存大小,可是不包含進程堆棧和代碼大小:

    SQL> select
    sum(bytes)/1024/1024 Mb
    from (
    select
    bytes
    from
    v$sgastat
    union
    select
    value bytes
    from
    v$sesstat s, v$statname n
    where
    n.STATISTIC# = s.STATISTIC# and
    n.name = ‘session pga memory‘
    );
    MB
    ----------
    517.296406

    在我的系統中,這個值要比通過任務管理器所示 VM值小約 30 Mb。
    當您確定 Oracle 就是那個正在大量使用內存的進程時。此查詢會顯示使用內存最多的會話

  3. Unix 系統:top 是一個很實用的工具,您能夠自己定義列顯示和基於keyword排序。ps 命令在大部分系統上都可用。但詳細用法不盡同樣。

    比如,在 Linux 系統上。“ps -AF --sort resident”會列出具有最大駐留集大小的全部進程。另請參閱“UNIX: Determining the Size of an Oracle Process”。

怎樣收集有關進程實際正在運行的任務的信息

這部分將僅僅討論 Oracle Server 進程。通過前面介紹的方法,您應該能夠確定一個或多個 Oracle Server 進程導致了內存消耗。請記住。並不是總是出現 ORA-4030 的進程導致了內存消耗,這個進程可能僅僅是無法申請到須要的內存而已。

對於不斷添加內存使用的進程。我們能夠在其執行時進行查看下面方面的信息:

  • 您能夠使用下面查詢檢查 v$sqlarea 從而找到進程正在運行的 SQL:

SQL> select

sql_text

from

v$sqlarea a, v$session s

where a.address = s.sql_address and

s.sid =<SID>;

我們能夠做heapdump,並將結果提交給 Oracle 技術支持:

SQL> select PID from v$process p, v$session s where p.addr=s.paddr and sid=<SID>;

SQL> oradebug setorapid <PID>
SQL> oradebug unlimit
SQL> oradebug dump errorstack 3
SQL> oradebug dump heapdump 536870917
SQL> oradebug tracefile_name (shows the path and filename information)
SQL> oradebug close_trace

假設問題間歇出現或某一進程因為報錯太快而導致無法進行檢查,且這個進程最有可能是內存消耗的原因。那麽,在進程錯誤發生時我們能夠使用下面事件來獲取 heapdump:
SQL> alter session set events ‘4030 trace name heapdump level 536870917‘;

或者在數據庫初始化文件裏設置此事件並又一次啟動實例。

- init.ora: event="4030 trace name heapdump level 536870917"
- spfile: 執行: SQL> ALTER SYSTEM SET EVENT=‘4030 trace name heapdump level 536870917‘ scope=spfile;

對於 低於 9.2.0.5 的版本號,請使用級別 5。而非級別 536870917。
Oracle技術支持project師可使用該heapdump查找過多內存分配的原因。

有關避免此錯誤的一般建議

  1. 如上所述。一些操作須要大量的內存。對於排序問題。降低 SORT_AREA_SIZE 會有所幫助。Oracle Server 進程會將 PGA 中的 SORT_AREA_SIZE 字節分配給排序操作。

    假設完畢搜索須要很多其它內存,server進程將會使用temporary segment。這意味著,降低 SORT_AREA_SIZE 會對須要大量排序操作的查詢性能產生影響。

  2. 對於 9i 及更高版本號,通過將參數 WORKAREA_SIZE_POLICY 設置為 AUTO,以及在初始化文件裏指定 PGA_AGGREGATE_TARGET 的大小,就可以啟用自己主動 SQL 運行內存管理功能。

    使用自己主動 PGA 內存管理將有助於降低發生 ORA-4030 錯誤的可能性。

    請註意,OpenVMS 操作系統在Oracle 9i版本號上不支持 PGA_AGGREGATE_TARGET。可是在 Oracle 10g 版本號上是支持的。

    有關很多其它具體信息,請參閱下面文檔:

    "Performance Issues After Increasing Workload",
    "Automatic PGA Memory Managment",
    "Top Oracle 9i init.ora Parameters Affecting Performance"

  3. PL/SQL 程序也可分配大量內存,因此可能須要重寫應用程序的某些部分。

    雖然 PL/SQL 表很easy使用,但它確實須要在 PGA 中分配內存。

  4. 查看 optimizer 策略,一些訪問路徑可能會因排序操作、較多行上的函數使用等原因而須要很多其它內存。

  5. 在某些操作系統上(比如 Microsoft Windows),可能要減少 SGA 的大小以便於 PGA 獲得更大的內存。

  6. 確保您的操作系統和 Oracle 限制設置合理。

  7. 確保有足夠的可用內存(物理內存和交換空間)。

參考

NOTE:199746.1 - How to Resolve ORA-4030 Errors on UNIX
NOTE:46001.1 - Oracle Database and the Windows NT memory architecture, Technical Bulletin
NOTE:116076.1 - Tackling ORA-4030 on Windows 32-bit Operating System
NOTE:67033.1 - OpenVMS: How Background Process Quotas are Set for Oracle RDBMS


NOTE:123754.1 - AIX: Determining Oracle Memory Usage On AIX
NOTE:174555.1 - UNIX: Determining the Size of an Oracle Process

NOTE:1088267.1 - Master Note for Diagnosing OS Memory Problems and ORA-4030



診斷並解決 ORA-4030 錯誤 (Doc ID 1548826.1)