Oracle 手動修改spfile後的現象記錄
Oracle 11G 引入Memory_max_target和Memory_target參數用於數據庫的內存自動管理(AMM),本意是修改該兩個參數超過物理內存的大小,視圖看看數據庫報什麼錯誤。
備份spfile文件
$cp spfileorcl.ora spfileorcl.ora.bak
直接手動修改spfile中的兩個參數值:
兩個值得大小分別修改為6,815,744,000,000≈6.7T 實際物理內存為16G左右
$ free -g
啟動數據庫出現如下報錯:
SQL> startup nomount;
ORA-01078: failure in processing system parameters
LRM-00109: could not open parameter file '/DBBK/oracle/product/11.2.0.1.0/dbs/initorcl.ora'
[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分配的大小不足,當該情況出現的時,通常是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這個隱參決定的
wKiom1ZmmFKCSpJnAAAqB8a8hkk265.png那麼得出一個結論:SGA的大小首先由與SGA有關的參數來決定。同理可以判斷PGA亦是如此。
總結:
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的自動分配關系。