Oracle Memory Usage on Solaris
The following is an introduction to reporting Oracle memory usage within the Sun Solaris environment. This article is geared towards both Oracle DBAs and UNIX (Solaris) System Administrators. However it can be used by anyone who would like to monitor memory used by Oracle on a Solaris system. This top is based on an article from Oracle.

 

UNDERSTANDING ORACLE PROGRAM TYPES

The first program type you should be aware of are the Oracle background processes. These processes are created when you start a database instance. Common examples of Oracle background processes are log writer (lgwr), database writer (dbw0), system monitor (smon), process monitor (pmon), recovery (reco), and check point (ckpt), but may include others. These processes run with the name ora_ProcessName_SID, where ProcessName is the name of the background process and SID
is the value of ORACLE_SID. For example, the process monitor background process for a database instance named DEV would be "ora_pmon_DEV".

The second program type you should be aware of are the Oracle user or client processes. These processes are created when you start a program which will work with an Oracle database. Common examples of Oracle user processes are sqlplus, imp, exp, and sqlldr, but may include many others. User processes are usually named the same as the command you used to start the program. For example, the sqlplus user process would be named "sqlplus".

The third program type you should be aware of are the Oracle shadow or server processes. Shadow processes work directly with the database instance to carry out the requests from the user processes.
Shadow processes may be dedicated to a single user process or part of a multi-threaded server (MTS) configuration. The shadow processes are named oracleSID, where SID is the value of ORACLE_SID.
For example, any shadow process connected to the database instance "DEV" would be named "oracleDEV".

UNDERSTANDING ORACLE MEMORY USAGE

Oracle memory usage can be broken down into 2 basic types, private and shared. Private memory is used only by a single process.

The largest segment of shared memory with Oracle is usually the Shared Global Area (SGA). The SGA is mapped into the virtual address space for all background and shadow processes. Many programs which display memory usage, like "top" or "ps -lf" do not distinguish between shared and private memory and show the SGA usage in each background and shadow process. Subsequently, it may appear as though Oracle is using several times more memory than what is actually installed on the system. To properly determine how much memory Oracle is using, you must use a tool
which separates private and shared memory. One such tool is"/usr/proc/bin/pmap".

A bourne shell script (omemuse), which relies on "/usr/proc/bin/pmap", is shown below. Oracle memory usage. For help with invocation options, run the script with the "h" parameter:

% omemuse h

The script will run pmap against Oracle processes that you specify, then reporthow much and what type of memory (private/shared) is being used. The value of private memory will be approximately the same for all oracle background processes, since all of these processes are just different
invocations of the same executable, $ORACLE_HOME/bin/oracle.

To see a snapshot of memory usage for all Oracle background and shadow processes, invoke omemuse as follows:

% omemuse SB

This will display the total private memory for all Oracle shadow processes, then the total private memory for all Oracle background processes, followed by the total shared memory used by all Oracle shadow and background processes, andfinally, the grand total of all memory used by this Oracle instance.

For more information about the pmap command and determining process memory usage, please refer to the following articles from Sun...

http://www.itworld.com/Comp/2402/UIR980301perf
http://www.sun.com/sun-on-net/performance/vmsizing.pdf

 

#!/usr/bin/sh
#
# Copyright 2001 Oracle Corporation
#
# program: omemuse (Oracle MEMory USagE)
# by Richard Gulledge
#
# modification history:
# date        by        comments
# ----------  --------  ----------------
# 11/15/1999  rgulledg  original program
# 04/16/2001  rgulledg  minor usage check mods
#

usage()
{
echo "Usage: $0 [ SB ]"
echo "Usage: $0 [ P 
 ]"
echo "Usage: $0 [ h ]"
echo " "
echo "specify 'S' for Oracle shadow processes"
echo "specify 'B' for Oracle background processes (includes shared memory SGA)"
echo "specify 'h' for help"
echo " "
}

echo " "

#
# check usage
#
if [ $# = "0" ];then
  usage;exit 1
fi
Parm1=$1
if [ $Parm1 = "h" ];then
  echo "This script uses the Sun Solaris pmap command to determine memory usage"
  echo "for Oracle server [B]ackground processes and/or [S]hadow processes."
  echo "An individual [P]rocess can also be specified."
  echo " "
  echo "Although the Oracle server background processes memory usage should"
  echo "remain fairly constant, the memory used by any given shadow process"
  echo "can vary greatly.  This script shows only a snapshot of the current"
  echo "memory usage for the processes specified."
  echo " "
  echo "The 'B' option shows the sum of memory usage for all Oracle server"
  echo "background processes, including shared memory like the SGA."
  echo " "
  echo "The 'S' option shows the sum of private memory usage by all"
  echo "shadow processes.  It does not include any shared memory like the"
  echo "SGA since these are part of the Oracle server background processes."
  echo " "
  echo "The 'P' option shows memory usage for a specified process, broken"
  echo "into two categories, private and shared.  If the same executable"
  echo "for this process was invoked again, only the private memory"
  echo "would be allocated, the rest is shared with the currently running"
  echo "process."
  echo " "
  usage;exit 1
fi
echo $Parm1|grep '[SBP]' > /dev/null
ParmFound=$?
if [ $ParmFound != "0" ];then
  usage;exit 1
fi
echo $Parm1|grep P > /dev/null
ParmFound=$?
if [ $ParmFound = "0" ];then
  if [ $Parm1 != "P" ];then
    usage;exit 1
  fi
  if [ "X$2" = "X" ];then
    usage;exit 1
  fi
  Parm2=$2
  echo $Parm2|grep '[^0-9]' > /dev/null
  ParmFound=$?
  if [ $ParmFound = "0" ];then
    usage;exit 1
  fi
  PidOwner=`ps -ef | grep -v grep | grep $Parm2 | grep -v $0 | awk '{print $1}'`
  CurOwner=`/usr/xpg4/bin/id -un`
  if [ "X$PidOwner" != "X$CurOwner" ];then
    echo "Not owner of pid $Parm2, or pid $Parm2 does not exist"
    echo " "
    usage;exit 1
  fi
else
  if [ "X${ORACLE_SID}" = "X" ];then
    echo "You must set ORACLE_SID first"
    usage;exit1
  fi
fi

#
# initialize variables
#
Pmap="/usr/proc/bin/pmap"
SharUse="/tmp/omemuseS$$"
PrivUse="/tmp/omemuseP$$"
ShadUse="/tmp/omemuseD$$"
PidPUse="/tmp/omemusePP$$"
PidSUse="/tmp/omemusePS$$"
TotalShad=0
TotalShar=0
TotalPriv=0
PidPriv=0
PidShar=0

#
# shadow processes
#
echo $Parm1|grep S > /dev/null
ParmFound=$?
if [ $ParmFound = "0" ];then
  ShadPrc="`ps -ef|grep -v grep|grep oracle$ORACLE_SID|awk '{print $2}'`"
  echo "" > $ShadUse
  for i in $ShadPrc;do
    $Pmap $i | grep "read/write" | grep -v shared | \
      awk '{print $2}' | awk -FK '{print $1}' >> $ShadUse
  done
  for i in `cat $ShadUse`;do
    TotalShad=`expr $TotalShad + $i`
  done
  TotalShad=`expr $TotalShad "*" 1024`
  echo "Total Shadow  (bytes) :	$TotalShad"
  /bin/rm $ShadUse
fi

#
# non-shared portion of background processes
#
echo $Parm1|grep B > /dev/null
ParmFound=$?
if [ $ParmFound = "0" ];then
  OrclPrc="`ps -ef|grep -v grep|grep ora_|grep $ORACLE_SID|awk '{print $2}'`"
  BkgdPrc="`echo $OrclPrc|awk '{print $1}'`"
  echo "" > $PrivUse
  for i in $OrclPrc;do
    $Pmap $i | grep "read/write" | grep -v shared | \
      awk '{print $2}' | awk -FK '{print $1}' >> $PrivUse
  done
  for i in `cat $PrivUse`;do
    TotalPriv=`expr $TotalPriv + $i`
  done
  TotalPriv=`expr $TotalPriv "*" 1024`
  echo "Total Private (bytes) :	$TotalPriv"

#
# shared portion of background processes
#
  echo "" > $SharUse
  $Pmap $BkgdPrc | grep "read/exec" | \
    awk '{print $2}' | awk -FK '{print $1}' >> $SharUse
  $Pmap $BkgdPrc | grep "shared" | \
    awk '{print $2}' | awk -FK '{print $1}' >> $SharUse
  for i in `cat $SharUse`;do
    TotalShar=`expr $TotalShar + $i`
  done
  TotalShar=`expr $TotalShar "*" 1024`
  echo "Total Shared  (bytes) :	$TotalShar"
  /bin/rm $SharUse $PrivUse
fi

#
# non-shared portion of pid
#
echo $Parm1|grep P > /dev/null
ParmFound=$?
if [ $ParmFound = "0" ];then
  echo "" > $PidPUse
  $Pmap $Parm2 | grep "read/write" | grep -v shared | \
    awk '{print $2}' | awk -FK '{print $1}' >> $PidPUse
  for i in `cat $PidPUse`;do
    PidPriv=`expr $PidPriv + $i`
  done
  PidPriv=`expr $PidPriv "*" 1024`
  echo "Total Private (bytes) :	$PidPriv"

#
# shared portion of pid
#
  echo "" > $PidSUse
  $Pmap $Parm2 | grep "read/exec" | awk '{print $2}' | \
    awk -FK '{print $1}' >> $PidSUse
  $Pmap $Parm2 | grep "shared" | awk '{print $2}' | \
    awk -FK '{print $1}' >> $PidSUse
  for i in `cat $PidSUse`;do
    PidShar=`expr $PidShar + $i`
  done
  PidShar=`expr $PidShar "*" 1024`
  echo "Total Shared  (bytes) :	$PidShar"
  /bin/rm $PidPUse $PidSUse
fi

#
# Display grand total
#
Gtotal="`expr $TotalShad + $TotalPriv + $TotalShar + $PidPriv + $PidShar`"
echo "			-----"
echo "Grand Total   (bytes) :	$Gtotal"
echo " "


				  
                    
This script is provided for educational purposes only. The script has been tested and appears to work as intended. However, you should always test any script before relying on it. No responsibility will be accepted for Lost or damage that may occur from it's use.