bit oracle由於位數限制使得oracle進程只能訪問g(的次方)以下的虛擬內存地址在很多時候這是一個很讓人頭疼的問題因為空著許多內存而不能使用而默認情況下SGA不能超過g比如我們的linux下有g內存卻有部分空著不能用干著急這個時候我們就要考慮怎樣擴展oracle的SGA那麼首先如何識別bit的oracle呢?我們可以通過如下查詢得到
sys@OCN> select * from v$version;
BANNER
Oraclei Enterprise Edition Release Production
PL/SQL Release Production
CORE Production
TNS for Linux: Version Production
NLSRTL Version Production
如果是bit oracle在查詢結果中一定會顯示 bit 字樣沒有出現則一定是bit oracle 當然在os上通過file oracle 也能看到
[oracle@ocn bin]$ cd $ORACLE_HOME/bin
[oracle@ocn bin]$ file oracle
oracle: setuid setgid ELF bit LSB executable Intel version dynamically linked (uses shared libs) not stripped
[oracle@ocn bin]$
在某些os上比如AIX上bit oracle 會正常顯示信息bit則不正常顯示
在確認了bit oracle之後我們要明白通常情況下我們的OS進程只能訪問g以下的空間redhat linux AS 或者AS版本例外他們可以提供VLM(Very large memory)功能支持使得通過轉換可以使用bit來標志內存地址那麼就是的次方理論上最大可支持g內存訪問在oracle中則是通過將內存當作文件來訪問的虛擬一個 /dev/shm 的文件系統這個文件系統是完全由內存組成的這樣將突破g的限制那回過來我們看看既然進程可以訪問g以下內存為何通常SGA又是g呢
在OS中規定了一個進程在應用程序中能訪問的虛擬內存空間為g而gg這段虛擬地址空間是保留給kernel使用的要注意我們這裡強調的是虛擬地址空間並沒有說物理地址空間也就是說假設有g的內存這g的虛擬地址空間可能出現在g內存的gg部分內存段並不是說是物理內存的g段而在這g的虛擬地址中oracle又是如何來使用的呢這是固定好了地址的
+++++++++++++++ g
+ +
+ +
+ +
+++++++++++++++ g: kernel
+ +
+ +
+ +
+++++++++++++++ g: process stack
+ +
+ +
+++++++++++++++ g: SGA起點
+++++++++++++++ g: oracle 共享庫裝載起點
+ +
+ +
+ +
+++++++++++++++ g: oracle program(可執行代碼)裝載起點
在這段虛擬地址的分配中g是sga的起點而進程的私有空間的分配(stack部分)卻是從靠近g處開始的也就是實際上SGA和進程私有空間是共用了gg這部分的由於進程私有空間特別小通常我們習慣性地認為SGA可以達到g進程私有空間有g足夠了從oracle一啟動開始或者從任何一用戶進程登陸開始所有虛擬地址的分配都已經固定好了只有用戶私有空間還可以擴展我們來看一下數據庫啟動後pmon進程(實際上任何一個進程都是一樣的)的虛擬地址分配情況由於我一台機器上跑著個數據庫所以我們看其中一個先看看數據庫SGA相關信息
[root@ocnsb root]# su oracle
[oracle@ocnsb oracle]$ sqlplus / as sysdba
SQL*Plus: Release Production on Mon Jul ::
Copyright (c) Oracle Corporation All rights reserved
Connected to:
Oraclei Enterprise Edition Release Production
With the Partitioning Real Application Clusters OLAP and Oracle Data Mining options
JServer Release Production
select>sys@OCN>select INSTANCE_NAME from v$instance ;
INSTANCE_NAME
roocn
show>sys@OCN>show sga
Total System Global Area bytes
Fixed Size bytes
Variable Size bytes
Database Buffers bytes
Redo Buffers bytes
sys@OCN>
exit>sys@OCN>exit
Disconnected from Oraclei Enterprise Edition Release Production
With the Partitioning Real Application Clusters OLAP and Oracle Data Mining options
JServer Release Production
[oracle@ocnsb oracle]$ ipcs
Shared Memory Segments
key shmid owner perms bytes nattch status
xabdc oracle
xccac oracle
Semaphore Arrays
key semid owner perms nsems status
xdf oracle
xd oracle
Message Queues
key msqid owner perms usedbytes messages
[oracle@ocnsb oracle]$
我這裡的共享內存段只有一個並且就是SGA的大小(shmid為)這是因為shnmax設置太大的緣故
[oracle@ocn kernel]$ more /proc/sys/kernel/shmmax
[oracle@ocn kernel]$
接下來我們看看PMON信息首先要找到pmon進程號然後去 /proc/pid/maps 中看該進程的虛擬地址分配信息
[oracle@ocnsb oracle]$ ps ef|grep pmon
oracle Jul ? :: ora_pmon_roocn
oracle Jul ? :: ora_pmon_ocn
oracle : pts/ :: grep pmon
[oracle@ocnsb oracle]$
[oracle@ocnsb oracle]$ more /proc//maps
aba rxp : /opt/oracle/products//bin/oracle
abaad rwp : /opt/oracle/products//bin/oracle
adae rwxp :
這部分是oracle program裝載信息我們可以看到空間使用了ae 這部分大小不足MB
rxp : /lib/ldso
這是oracle 共享庫裝載的起點x 正好是g
rwp : /lib/ldso
rwp :
rxp : /opt/oracle/products//lib/libodmdso
a rwp : /opt/oracle/products//lib/libodmdso
a rxp : /opt/oracle/products//lib/libskgxpso
a rwp b : /opt/oracle/products//lib/libskgxpso
a rxp : /opt/oracle/products//lib/libskgxnso
rwp d : /opt/oracle/products//lib/libskgxnso
d rwp :
dc rxp : /opt/oracle/products//lib/libjoxso
cc rwp de : /opt/oracle/products//lib/libjoxso
ce rwp :
e rxp : /lib/libdlso
rwp : /lib/libdlso
rwp :
rxp : /lib/libmso
rwp : /lib/libmso
rxp : /lib/libpthreadso
d rwp e : /lib/libpthreadso
d rxp : /lib/libnslso
rwp : /lib/libnslso
rwp :
rxp : /usr/lib/libaioso
rwp : /usr/lib/libaioso
ca rxp : /lib/libcso
cacf rwp : /lib/libcso
cfd rwp :
dd rxp : /lib/libredhatkernelso
dd rwp : /lib/libredhatkernelso
df rwp :
fa rxp : /lib/libnss_filesso
rwp : /lib/libnss_filesso
rwp : /dev/zero
c rwp :
共享庫消耗了不到MB的空間
b rws : /SYSVabdc (deleted)
這是SGA的起點x 表示g
bb rs b : /SYSVabdc (deleted)
bba rws b : /SYSVabdc (deleted)
baba rs ba : /SYSVabdc (deleted)
bab rws ba : /SYSVabdc (deleted)
sga虛擬空間分配到這裡通過計算進制數正好和我們的SGA大小吻合就是我們在ipcs查看的時候的 shmid
bffebffee rwxp ffff :
bfffbfff rxs : /dev/vsys
由於xc正好是g(進制數c=*=x表示g)則這裡表示進程私有空間的分配的起點查看oracle任何一個用戶登陸進程也將發現這樣的虛擬地址分配在這裡我們很容易看出來oracle program 和共享內存庫所占用的空間很小沒有必要給那麼大實際上oracle program 給M足夠安全而共享庫給M也足夠安全了也就是從理論上來講我們可以把oracle program所需要壓縮在x以下共享庫所需要內存壓縮在x以下這樣SGA的起點就可以提升到x(g)而原來是從x(g)開始的只有大約g分配給SGA現在從g開始分配SGA則可以接近g比如分配g內存給SGA要實現這個功能我們需要重新編譯oracle program降低共享庫虛擬內存分配的地址和SGA的分配起點位置x這個共享庫裝載的起點是由進程的mapped_base來決定的
[oracle@ocnsb oracle]$ more /proc//mapped_base
這個大小是G則意味著共享庫的裝載從虛擬地址的g位置開始如果要降低這個地址需要在oracle啟動之前也就是用root用戶把將啟動oracle的進程的mapped_base降低到M這樣oracle啟動之後的產生的進程都將繼承這個值
su root echo > /proc//mapped_base
當然我們也可以通過一些shell來實現oracle用戶登陸之後自動降低mapped_base的功能這個在google上就能找到了或者參考
中文章內容如下
Giving Oracle Users the Privilege to Change the Base Address for Oracles Shared Libraries Without Giving them root Access
As shown above only root can change the base address mapped base for shared libraries Using sudo we can give Oracle users the privilege to change mapped base for their own shells without giving them full root access Here is the procedure:
su root
# Eg create a script called /usr/local/bin/ChangeMappedBase
# which changes the mapped base for the parent process
# the shell used by the Oracle user where the sudo program # is executed (forked) Here is an example:
#/bin/sh
# Lowering mapped base to x echo > /proc/$PPID/mapped_base
# Make sure that owernship and permissions are correct chown rootroot /usr/local/bin/ChangeMappedBase
chmod /usr/local/bin/ChangeMappedBase
# Allow the Oracle user to execute /usr/local/bin/ChangeMappedBase via sudo echo oracle ALL=/usr/local/bin/ChangeMappedBase >> /etc/sudoers
Now the Oracle user can run /usr/local/bin/ChangeMappedBase to change mapped base for its own shell:
$ su oracle
$ cat /proc/$$/mapped_base; echo
$ sudo /usr/local/bin/ChangeMappedBase Password:
# type in the password for the Oracle user account
$ cat /proc/$$/mapped_base; echo $
When /usr/local/bin/ChangeMappedBase is executed the first time after an Oracle login sudo will ask for a password The password that needs to be entered is the password of the Oracle user account
Changing the Base Address for Oracles Shared Libraries Automatically During an Oracle Login
The procedure in the previous section asks for a password each time /usr/local/bin/ChangeMappedBase is executed the first time after an Oracle login To have mapped base changed automatically during an Oracle login without a password the following can be done:
Edit the /etc/sudoers file with visudo:
su root visudo
Change the entry in /etc/sudoers from:
oracle ALL=/usr/local/bin/ChangeMappedBase
to read:
oracle ALL=NOPASSWD: /usr/local/bin/ChangeMappedBase
Make sure bash executes /usr/local/bin/ChangeMappedBase during the login process You can use eg ~oracle/bash_profile:
su oracle echo sudo /usr/local/bin/ChangeMappedBase >> ~/bash_profile
The next time you login to Oracle the base address for shared libraries will bet set automatically
$ ssh oracle@localhost
oracle@localhosts password: Last login: Sun Apr :: from localhost
$ cat /proc/$$/mapped_base; echo $
SGA起點從g降低到g則需要重新編譯oracle program必須要強調的是SGA的起點是和共享庫的起點mapped_ase相關的SGA的起點至少得大於共享庫的起點g以上才是安全的否則數據庫將不能啟動或者崩潰
關閉oracle
su oracle
cd $ORACLE_HOME/rdbms/lib
修改共享庫裝載地址的文件定義
genksms s x > ksmss
編譯好目標文件
make f ins_rdbmsmk ksmso
重新編譯oracle可執行文件
make f ins_rdbmsmk ioracle
至於 redhat linux AS 以上版本 oracle的VLM的使用則也是比較簡單的了參考
當然internet上還有更多文章可以供參考
在這裡我要指出一個問題也是我們在實踐中遇到的一個問題那就是若SGA分配的很大但沒有使用VLM幾乎很靠近g的時候大約只留下m左右這樣當一個進程進行hash join由於我們的pga_aggregate_target設置為goracle默認單個進程使用PGA可以達到pga_aggregate_target * % = M則使得在進行hash join的時候出錯
ORA: out of process memory when trying to allocate bytes (hashjoin subhkllcqas:kllsltba)
我們調整pga_aggregate_target減小到M則該查詢執行成功因為沒有使用VLM的情況下單個進程的內存分配空間必須在g以下而PGA的分配也屬於這個范疇如果使用VLM則PGA已經被分配到g以上部分的虛擬地址不再有這個問題在此不再對VLM進行過多的闡述因為使用也比較簡單從原理上來講就是通過os擴展bit 到bitoracle使用文件來管理內存並支持進程訪問g以上部分的虛擬內存linux上這種用法得到推廣的根本原因是因為其bit oracle很少被使用其他如sunOS/hp unix/AIX 等都廣泛使用bit oracle了這些方法也就失去價值了
From:http://tw.wingwit.com/Article/program/Oracle/201311/16567.html