Oracle 11G 引入Memory_max_target和Memory_target參數用於數據庫的內存自動管理(AMM),本意是修改該兩個參數超過物理內存的大小,視圖看看數據庫報什麼錯誤。linux
備份spfile文件數據庫
$cp spfileorcl.ora spfileorcl.ora.baksession
直接手動修改spfile中的兩個參數值:oracle
兩個值得大小分別修改成6,815,744,000,000≈6.7T 實際物理內存爲16G左右app
$ free -gless
啓動數據庫出現以下報錯:ide
SQL> startup nomount;
ui
ORA-01078: failure in processing system parametersthis
LRM-00109: could not open parameter file '/DBBK/oracle/product/11.2.0.1.0/dbs/initorcl.ora'spa
[oracle@021Y-SH-BKAP dbs]$ oerr ora 1078
01078, 00000, "failure in processing system parameters"
// *Cause: Failure during processing of INIT.ORA parameters during system startup.
// *Action: Further diagnostic information should be in the error stack.
[oracle@021Y-SH-BKAP dbs]$ oerr lrm 109
109, 0, "could not open parameter file '%.*s'"
// *Cause: The parameter file does not exist.
// *Action: Create an appropriate parameter file.
理論上我修改memory_target參數應該報錯memory_target值不符合物理內存的配置,但實際報的倒是找不到pfile。是否是說明手動修改spfile會致使spfile沒法正常讀取呢?
手動將這兩個參數的值修改爲原值,發現啓動時依舊一樣的錯誤。能夠判斷手動修改spfile確實形成異常。經過file命令查看spfile.ora能夠知道該文件的類型是二進制的數據文件類型。
$ file spfile.ora
spfile.ora: data
還原正常了spfile備份文件
SQL> show parameter spfile;
NAME TYPE VALUE
-------- ---------- ------------------------------
spfile string /DBBK/oracle/product/11.2.0.1.0/dbs/spfileorcl.ora
經過DDL語句我嘗試了屢次修改這兩個參數超出物理內存值,發現一些頗有趣的現象:
SQL> select * from v$version;
BANNER
-------------------------------------------------------------------------------------------
Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - 64bit Production
PL/SQL Release 11.2.0.1.0 - Production
CORE 11.2.0.1.0 Production
TNS for Linux: Version 11.2.0.1.0 - Production
NLSRTL Version 11.2.0.1.0 - Production
SQL> alter system set memory_max_target=6800G scope=spfile;
SQL> alter system set memory_target=6500G scope=spfile;
System altered.
大多數狀況下調整後,數據庫都能正常加載spfile文件中的配置,但偶爾也出現以下報錯。先記錄下來,再逐一分析
SQL> startup nomount;
ORA-00845: MEMORY_TARGET not supported on this system
SQL> startup nomount;
ORA-04031: unable to allocate 56 bytes of shared memory ("shared pool","unknown object","sga heap(2,1)","fixed allocation callback")
SQL> startup nomount;
ORA-04031: unable to allocate 10272 bytes of shared memory ("shared pool","unknown object","sga heap(1,0)","KGLSG")
觀察第一個報錯的狀況:
$ oerr ora 845
00845, 00000, "MEMORY_TARGET not supported on this system"
// *Cause: The MEMORY_TARGET parameter was not supported on this operating system or /dev/shm was not sized correctly on Linux.
// *Action: Refer to documentation for a list of supported operating systems. Or, size /dev/shm to be at least the SGA_MAX_SIZE on each Oracle instance running on the system.
能夠看到錯誤告警的解釋是memory_target參數在該系統不支持,或者是/dev/shm分配的大小不足,查看告警日誌獲取啓動信息:
Starting ORACLE instance (normal)
WARNING: You are trying to use the MEMORY_TARGET feature. This feature requires the /dev/shm file system to be mounted for at least 536870912000 bytes. /dev/shm is either not mounted or is mounted with available space less than this size. Please fix this so that MEMORY_TARGET can work as expected. Current available is 8363978752 and used is 0 bytes. Ensure that the mount point is /dev/shm for this directory.
一樣說明了狀況,shm內存分配不足,這是linux系統的共享內存形式,根據linux本質一切皆文件的定義。linux的共享內存也被定爲一個可掛在的分區系統文件tmpfs。當memory_target超過這一限制時,可能會致使相似的報錯的產生。
$ df -Ph
Filesystem Size Used Avail Use% Mounted on
tmpfs 7.8G 1017M 6.8G 13% /dev/shm
但這樣的報錯並不僅僅是由Memory_target參數影響的。不管如何修改memory_target和memory_max_target的值超過實際內存大小。該報錯都不能保證發生,當我將sga_max_size和sga_target設置的值超過實際物理內存時,反而觸發了該報錯。爲何呢?
觀察啓動能夠看到,數據庫加載spfile時候是根據sga_max_size和sga_target來進行SGA的分配的,只要該參數設置合理。即便Memory_target設置的再不合理,數據庫也能正常啓動。那麼我是否是能夠理解爲當應用請求更多的內存並超過了sga_max_size的值或者sga_max_size和sga_target值均未分配的時候,數據庫的內存管理才真正由memory_target和memory_max_target值來決定?
SQL> alter system set sga_max_size=0 scope=spfile;
SQL> alter system set sga_target=0 scope=spfile;
SQL> startup nomount;
ORACLE instance started.
Total System Global Area 1068994560 bytes
Fixed Size 2220072 bytes
Variable Size 671092696 bytes
Database Buffers 390070272 bytes
Redo Buffers 5611520 bytes
當我修改後,發現實際SGA自動分配了1G左右的內存。這個是由Memory_target來決定的嗎?答案也不是。查看隱參。發現SGA默認大小實際是由__sga_target這個隱參決定的
那麼得出一個結論:SGA的大小首先由與SGA有關的參數來決定。同理能夠判斷PGA亦是如此。
如今咱們在來看看這個報錯
ORA-04031: unable to allocate 56 bytes of shared memory ("shared pool","unknown object","sga heap(2,1)","fixed allocation callback")
很明顯提示說不能再分配給shared memory 56bytes的空間,後面的細節也說明是分配的對象是shared pool
04031, 00000, "unable to allocate %s bytes of shared memory (\"%s\",\"%s\",\"%s\",\"%s\")"
// *Cause: More shared memory is needed than was allocated in the shared
// pool.
// *Action: If the shared pool is out of memory, either use the
// DBMS_SHARED_POOL package to pin large packages,
// reduce your use of shared memory, or increase the amount of
// available shared memory by increasing the value of the
// initialization parameters SHARED_POOL_RESERVED_SIZE and
// SHARED_POOL_SIZE.
// If the large pool is out of memory, increase the initialization
// parameter LARGE_POOL_SIZE.
能夠看到給出的解決方式要麼用DBMS_SHARED_POOL去PIN住較大的內存從而減小共享內存的分配,或者經過修改SHARED_POOL_RESERVED_SIZE和SHARED_POOL_SIZE來增大內存的分配。
而其中提示sga heap(2,1)的信息來自哪?
嘗試轉儲shared pool的信息:
alter session set events 'immediate trace name heapdump level 2';
總結:
11G之後引入了memory_max_target和memory_target參數進行內存的自動化管理(Automatic Memory Management),但實際上SGA和PGA的分配仍是由各自的參數先行決定,好比sga_target、sga_max_size、pge_aggregate_target。
PGA和SGA默認值實際分別有__pga_aggregate_target和__sga_target隱參來決定。
AMM管理的是SGA和PGA的分配關係,ASMM(Automatic Shared Memory Management)則管理的是SGA的各組件的分配關係,ASEMM(Automated SQL Execution Memory Management)則是管理PGA的自動分配關係。