Post on 16-Apr-2015
Wasting expensive RAM resources is a bad thing and the goal of the Oracle DBA
is to maximize the SGA region with intelligent SGA sizing techniques in relation
tosga_max_size.
Beware of AMM:
There are reports where automatic memory management (implemented by
setting the sga_target and sga_max_size parameters) can cause performance
problem, especially for databases with undersized RAM resources.
Oracle (AMM) resize operations can hurt performance.
In 11g and beyond, Oracle automatic memory management is configured
using the memory_target and memory_max_target initialization
parameters. The memory_target parameter specifies the amount of shared
memory available for Oracle to use when dynamically controlling the SGA
and PGA. Thememory_max_target AMM parameter specifies the max size
thatmemory_target may take.
Note that larger shops many forgo AMM and manually size
their shared_pool_size anddb_cache_size. A human DBA can frequently do a
better job in sizing the RAM pools, especially when using predictive tuning
techniques, which anticipate changes in workload and adjust the pools before a
shortage occurs.
If you only have Oracle on the server, start by reserving 10% of RAM for Linux or
20% or RAM for Windows. With whatever RAM is left-over you allocate to SGA
and PGA:
sga_max_size -- This 10g parameter sets the hard limit up to which sga_targetcan
dynamically adjust sizes. At database start time, Oracle will allocatesga_max_size in
RAM (or set sga_max_size to the sum of the existing pool sizes), so in order not to
waste RAM it may be a good idea to havesga_max_size and sga_target at the same
value, but there may be times when you want to have the capability to adjust for peak
loads. By setting this parameter higher than sga_target, you allow dynamic
adjustment of the sga_targetparameter. For related notes, see MOSC Notes
295626.1, 396940.1, 270065.1 and 256913.1.
sga_target -- This parameter is for Oracle Database 10g ONLY and reflects the total
size of memory footprint a SGA can consume. It includes in its boundaries the fixed
SGA and other internal allocations, the (redo) log buffers, the shared pool, Java pool,
streams pool, buffer cache, keep/recycle caches, and if they are specified, the non-
standard block size caches.
AIX Note for sga_target: There are reported cases where sga_target cannot exceed two
gigabytes. This is because of the need to edit edit the /etc/security/limits file and
look for Soft DATA segment, it should have the value of -1 (Unlimited).
What should be my sga_max_size?
The default that oracle suggests at the DBCA is 40%, however, the appropriate size for this
parameter depends on the space requirements of your actual SGA. Your application
requirements will determine this, things like the amount of concurrent users and the activities
they are really performing. These types of things can only be monitored when running
processes. There is no formula for an exact value of these parameters. The best thing you can
do is to tune based the advisors suggestions.
Memory consumption should be checked when your real workload is in progress,
andsga_max_size tuning should be performed using Enterprise Manager to tune based on
realistic metrics.
You can see the Oracle memory segments with the ipcs -pmb command.
Question: Can you please explain the Oracle sga_max_size parameter?
Answer: Wasting expensive RAM resources is a bad thing and the goal of the
Oracle DBA is to maximize the SGA region with intelligent SGA sizing
techniques in relation tosga_max_size.
The sga_max_size was introduced for databases where the DBA did not know how
to optimize the SGA pools manually. Today, a competent DBA can do a better job
that automatic shared memory management, and large Oracle database still use
manual SGA pool sizing.
The Oracle sga_max_size parameter sets the hard limit up to which sga_target can
dynamically adjust sizes. Usually, sga_max_size and sga_target will be the same
value, but there may be times when you want to have the capability to adjust for
peak loads. By setting the Oracle sga_max_size parameter higher than sga_target,
you allow dynamic adjustment of the sga_target parameter.
AIX Note for sga_target: There are reported cases where sga_target cannot exceed two
gigabytes. This is because of the need to edit the /etc/security/limitsfile and look for
Soft DATA segment, it should have the value of -1 (Unlimited).
Beware OF AMM:
There are reports where automatic memory management (implemented by setting
the sga_targetand sga_max_size parameters) can cause performance problem, especially for
databases with undersized RAM resources.
See Oracle (AMM) resize operations can hurt performance. In sum, all large mission-critical databases should have an expert DBA manually configure
and optimize their SGA pool sizes.
Also, larger shops many forgo AMM and manually size
their shared_pool_size anddb_cache_size. A human DBA can frequently do a better job in
sizing the RAM pools, especially when using predictive tuning techniques, which anticipate
changes in workload and adjust the pools before a shortage occurs.
Note that sga_max_size is for Oracle 10g only, and in 11g and beyond, Oracle automatic
memory management is configured using
the memory_target and memory_max_target initialization parameters. The memory_target
parameter specifies the amount of shared memory available for Oracle to use when
dynamically controlling the SGA and PGA. The memory_max_target AMM parameter
specifies the max size that memory_target may take.
See my additional notes on Oracle sga_max_size:
I'm consolidating 15 Oracle instances onto a single server and I need advice on the proper
way to size my SGA for each instance.
Answer:
In a shared environment, it's important to observe the optimal sizes for
eachshared_pool_size (v$shared_pool_advice) and the optimal data buffer size
(usingv$db_cache_advice). I have complete Oracle SGA sizing details in my book "Oracle
Tuning: The Definitive Reference".
Make sure to tread these detailed notes on SGA sizing.
2007 PGA Update: Oracle technology is constantly changing, so don't miss my new notes
on updates to Oracle PGA behavior. Also see these important notes on over-riding the Oracle
PGA defaults.
In 10g, you may consider using Automatic Memory Management (AMM) and set
thesga_max_size parameter to give the total SGA allocation.
Wasting expensive RAM resources is a bad thing and the goal of the Oracle DBA is to
maximize the SGA region with intelligent SGA sizing techniques.
If you only have Oracle on the server, start by reserving 10% of RAM for Linux or 20% or
RAM for Windows. With whatever RAM is left-over:
SGA Sizing - Optimize the instance by determining the optimal size
fordb_cache_size, shared_pool_size, etc.
PGA Sizing - Determine the optimal total RAM for PGA regions
(pga_aggregate_target) to minimize disk sorts and maximize hash joins
Sizing your SGA
The SGA sizing tasks include optimizing settings for sga_max_size (not recommended for
large databases where manual allocation is more effective) and the various configuration
parameters for db_cache_size, db_xk_cache_size, shared_pool_size, large_pool_size, and
other memory objects give the dba better control of system global area (SGA) component
sizing. Some parameters to consider in SGA sizing include:
sga_max_size -- This parameter sets the hard limit up to which sga_target can
dynamically adjust sizes. Usually, sga_max_size and sga_target will be the same
value, but there may be times when you want to have the capability to adjust for peak
loads. By setting this parameter higher than sga_target, you allow dynamic
adjustment of the sga_target parameter.
sga_target -- This parameter is new in Oracle Database 10g and reflects the total size
of memory footprint a SGA can consume. It includes in its boundaries the fixed SGA
and other internal allocations, the (redo) log buffers, the shared pool, Java pool,
streams pool, buffer cache, keep/recycle caches, and if they are specified, the non-
standard block size caches.
SGA Sizing on a dedicated server
For dedicated Oracle servers, the maximum total RAM SGA size can be computed as
follows:
OS Reserved RAM – This is RAM required to run the OS kernel and system
functions, 20% of total RAM for MS-Windows, and 10% of total RAM for UNIX/Linux
Oracle Database Connections RAM – Each Oracle connection requires OS RAM
regions for sorting and hash joins. (This does not apply when using the Oracle multi-
threaded server or pga_aggregate_target .) The maximum amount of RAM required for a
session is as follows:
2 megabytes RAM session overhead
+ sort_area_size
+ hash_area_size
Oracle SGA Sizing for RAM – This is determined by the Oracle parameter settings.
The total is easily found by either the show sga command or the value of
thesga_max_size parameter.
We should subtract 20 percent from the total available RAM to allow for MS-Windows
overhead. Windows uses RAM resources even when idle, and the 20 percent deduction is
necessary to get the real free RAM on an idle server. Once the amount of RAM on the server
is known, we will be in a position to size the Oracle SGA for optimal RAM usage.
Oracle RAM on MS-Windows
To see how much RAM you have on your MS-Windows server, you can go to start -->
settings > control panel --> system, and click on the "general" tab (refer to Figure 1). Here
we see that this server has 1,250 megabytes of RAM.
The MS-windows system display screen.
Now that we know how to tell the size of our MS-Windows RAM and the size of the SGA,
we have to consider the RAM usage for Oracle connections.
Monitoring Server Resources in MS-Windows
In MS-Windows we can use the performance manager screen to observe the resource
consumption of the Oracle Windows server (refer to Figure 2). The performance manager is
hidden deep inside the Windows menus, but can be found by following start > settings >
control panel > administrative tools > performance.
The MS-Windows server performance monitor.
The MS-Windows performance monitor plots three metrics:
Green (CPU) - This is the percentage of CPU resources consumed
Yellow (RAM) - This is the number of RAM pages per seconds used
Blue (DISK) - This is the disk I/O queue length percentage
Let's take a closer look at the MS-Windows performance monitor. Figure 2 is a time-based
snapshot of an Oracle databases resource consumption at startup time. These lines form
signatures (known usage patterns) that reveals some interesting patterns inside Oracle:
1. RAM Usage The yellow line is RAM usage, and we see the first spike in the RAM when
the SGA is allocated and a short spike in RAM as the database is mounted.
2. DISK Usage The blue line is the disk I/O, and we see the disk I/O activity peg at the point
where we mount the database. This is because Oracle must touch every data file header to
read the system change number (SCN).
3. CPU Usage The green line is CPU and it is interesting to note that the CPU never goes
above 50% during Oracle database startup.
Conclusion
For PGA sizing, we need to know the high water mark (HWM) of Oracle connections and the
average RAM needs to minimize disk sorts and maximize hash joins.
The high water mark of connected Oracle sessions can be determined in several ways. One
popular method uses Oracle login and logoff system-level triggers to record sessions in a
statistics table.
Another method uses Oracle STATSPACK to display the values from the stats$sysstat
table, or the v$resource_limit view (only after release 8.1.7, because of a bug).
In sum, SGA sizing is relatively straightforward push-pull of the competing RAM needs of
the internal SGA pools (buffer, library cache), the external RAM for PGA, and the OS
overhead.
If you like Oracle tuning, you may enjoy my new book
"Oracle Tuning: The Definitive Reference", over 900
pages of BC's favorite tuning tips & scripts.
You can buy it direct from the publisher for 30%-off and
get instant access to the code depot of Oracle tuning
scripts.
n this post, I am going to be demonstrating the basics of working of the sga_max_size
and sga_target and also to cover some myths of playing around with these parameters.
To begin with, sga_max_size is set in the spfile to a value of 200M and then I try to set
the sga_target and the story unfolds as below.
SQL> sho parameter spfile
NAME TYPE VALUE
------------------------------------ ----------- --------------------------
----
spfile string
/opt/app/oracle/product/10.2.0
/dbs/spfileprod_db.ora
SQL> sho parameter sga_
NAME TYPE VALUE
------------------------------------ ----------- --------------------------
----
sga_max_size big integer 200M
sga_target big integer 0
SQL> sho sga
Total System Global Area 209715200 bytes
Fixed Size 1977560 bytes
Variable Size 155194152 bytes
Database Buffers 50331648 bytes
Redo Buffers 2211840 bytes
SQL> sho parameter shared_pool_size
NAME TYPE VALUE
------------------------------------ ----------- --------------------------
----
shared_pool_size big integer 84M
SQL> sho parameter db_cache_size
NAME TYPE VALUE
------------------------------------ ----------- --------------------------
----
db_cache_size big integer 48M
SQL> sho parameter large
NAME TYPE VALUE
------------------------------------ ----------- --------------------------
----
large_pool_size big integer 0
SQL> sho parameter java_pool_size
NAME TYPE VALUE
------------------------------------ ----------- --------------------------
----
java_pool_size big integer 24M
SQL> sho parameter streams_pool
NAME TYPE VALUE
------------------------------------ ----------- --------------------------
----
streams_pool_size big integer 0
Now, trying to set the sga_target to a value of 210M which is greater than that of
sga_max_size gives out an error of ORA-02097 and ORA-00823, this shows that the
sga_target can never be greater than the sga_max_size.
SQL> alter system set sga_target=210M scope=both;
alter system set sga_target=210M scope=both
*
ERROR at line 1:
ORA-02097: parameter cannot be modified because specified value is invalid
ORA-00823: Specified value of sga_target greater than sga_max_size
However, sga_target can be set less than or equal to sga_max_size.
SQL> alter system set sga_target=200M scope=both;
System altered.
SQL> sho parameter sga_
NAME TYPE VALUE
------------------------------------ ----------- --------------------------
----
sga_max_size big integer 200M
sga_target big integer 200M
But an interesting point to be noted in here is that as soon as the sga_target is set to a
non-zero value, it starts affecting the memory areas of the SGA which is evident from
the change in the value of Database Buffers (db_cache_size) from 50331648 (48M) from
the previous execution of SHO SGA to 92274688 (88M), while every other memory area
remains unchanged.
SQL> sho sga
Total System Global Area 209715200 bytes
Fixed Size 1977560 bytes
Variable Size 113251112 bytes
Database Buffers 92274688 bytes
Redo Buffers 2211840 bytes
SQL> sho parameter db_Cache_size
NAME TYPE VALUE
------------------------------------ ----------- --------------------------
----
db_cache_size big integer 88M
SQL> sho parameter shared_pool_size
NAME TYPE VALUE
------------------------------------ ----------- --------------------------
----
shared_pool_size big integer 84M
SQL> sho parameter java_pool
NAME TYPE VALUE
------------------------------------ ----------- --------------------------
----
java_pool_size big integer 24M
SQL> sho parameter streams_pool
NAME TYPE VALUE
------------------------------------ ----------- --------------------------
----
streams_pool_size big integer 0
SQL> sho parameter large_pool
NAME TYPE VALUE
------------------------------------ ----------- --------------------------
----
large_pool_size big integer 0
Let's try to unset the sga_target and see if Database Buffers (db_cache_size) reverts
back to what it was, but it does not.
SQL> alter system set sga_target=0 scope=both;
System altered.
SQL> sho sga
Total System Global Area 209715200 bytes
Fixed Size 1977560 bytes
Variable Size 113251112 bytes
Database Buffers 92274688 bytes
Redo Buffers 2211840 bytes
SQL> sho parameter sga_
NAME TYPE VALUE
------------------------------------ ----------- --------------------------
----
sga_max_size big integer 200M
sga_target big integer 0
SQL> sho parameter db_Cache_size
NAME TYPE VALUE
------------------------------------ ----------- --------------------------
----
db_cache_size big integer 88M
It was hoped that bouncing the database would make a difference, on the contrary it did
not. It is another discussion as to why the Database Buffers (db_Cache_size) does not
change back to what it was even after unsetting the sga_target and bouncing the
database, let's not get into the nitty-gritty of that.
SQL> sho sga
Total System Global Area 209715200 bytes
Fixed Size 1977560 bytes
Variable Size 113251112 bytes
Database Buffers 92274688 bytes
Redo Buffers 2211840 bytes
SQL> sho parameter db_Cache_size
NAME TYPE VALUE
------------------------------------ ----------- --------------------------
----
db_cache_size big integer 88M
SQL> shut immediate
Database closed.
Database dismounted.
ORACLE instance shut down.
SQL> startup
ORACLE instance started.
Total System Global Area 209715200 bytes
Fixed Size 1977560 bytes
Variable Size 113251112 bytes
Database Buffers 92274688 bytes
Redo Buffers 2211840 bytes
Database mounted.
Database opened.
SQL> sho parameter sga_
NAME TYPE VALUE
------------------------------------ ----------- --------------------------
----
sga_max_size big integer 200M
sga_target big integer 0
SQL> sho parameter db_Cache_size
NAME TYPE VALUE
------------------------------------ ----------- --------------------------
----
db_cache_size big integer 88M
The Oracle server does not let you to resize the sga_max_size on the fly since it is not a
dynamically changeable parameter. Let's now change sga_target to the value of
sga_max_size. After this I will comment the sga_max_size and add sga_target=200M in
the pfile, convert it into spfile and bounce the database.
SQL> sho parameter sga_
NAME TYPE VALUE
------------------------------------ ----------- --------------------------
----
sga_max_size big integer 200M
sga_target big integer 0
SQL> alter system set sga_max_size=0 scope=both;
alter system set sga_max_size=0 scope=both
*
ERROR at line 1:
ORA-02095: specified initialization parameter cannot be modified
SQL> alter system set sga_target=200M scope=both;
System altered.
SQL> sho parameter sgA_
NAME TYPE VALUE
------------------------------------ ----------- --------------------------
----
sga_max_size big integer 200M
sga_target big integer 200M
### MAIN SGA PARAMS ###
###sga_max_size=200M
sga_target=200M
SQL> create spfile from pfile;
File created.
SQL> startup
ORACLE instance started.
Total System Global Area 209715200 bytes
Fixed Size 1977528 bytes
Variable Size 75502408 bytes
Database Buffers 130023424 bytes
Redo Buffers 2211840 bytes
Database mounted.
Database opened.
SQL> sho parameter sga_
NAME TYPE VALUE
------------------------------------ ----------- --------------------------
----
sga_max_size big integer 200M
sga_target big integer 200M
SQL> sho parameter db_cache_size
NAME TYPE VALUE
------------------------------------ ----------- --------------------------
----
db_cache_size big integer 0
SQL> sho parameter shared_pool_size
NAME TYPE VALUE
------------------------------------ ----------- --------------------------
----
shared_pool_size big integer 0
SQL> sho parameter large_pool
NAME TYPE VALUE
------------------------------------ ----------- --------------------------
----
large_pool_size big integer 0
SQL> sho parameter java_pool_s
NAME TYPE VALUE
------------------------------------ ----------- --------------------------
----
java_pool_size big integer 0
SQL> sho parameter streams_pool
NAME TYPE VALUE
------------------------------------ ----------- --------------------------
----
streams_pool_size big integer 0
SQL>
It now shows that as soon as the sga_target is set and set_max_size is unset, all the
other memory area related parameters get reset to a value of zero(0) - making it clear
that the Automatic Shared Memory Management is fully functional and that Memory
Manager (MMAN) background process is actively doing its job. Also has the Database
Buffers (db_cache_size) taken a higher value of 130023424 (124M) against the previous
88M.
There is yet another point to be noted here, besides sga_max_size being commented in
spfile - it takes a value equal to the sga_target.
SQL> sho parameter sga_
NAME TYPE VALUE
------------------------------------ ----------- --------------------------
----
sga_max_size big integer 200M
sga_target big integer 200M
UNIX$> grep -i "sga" initprod_db.ora
###sga_max_size=200M
sga_target=200M
UNIX$> grep -i "sga" $ORACLE_HOME/dbs/spfileprod_db.ora
*.sga_target=200M
The conclusions that we can draw from these little experiments are listed
below.
1) sga_max_size cannot be changed without bouncing the database.
2) sga_target can be changed on the fly without bouncing the database but it
can never be set to a value greater than the sga_max_size.
3) If the sga_max_size is not set in either of the pfile or spfile and the
sga_target is set then the sga_max_size takes the value of sga_target when
you do a sho parameter sga_
How to increase SGA_MAX_SIZE in
Oracle Phillip Bracken, Database Architect, Wachovia Corporate & Investment Banking
How can I increase SGA_MAX_SIZE in Oracle ? I got the error "ORA-03113: end-of-file on
communication channel" during startup. Please help me with the steps to increase the SGA. I'm
connected to Oracle9i Enterprise Edition Release 9.0.1.1.1 (Production) with the partitioning
option.
SQL> connect sys as sysdba Enter password: ****** Connected. SQL> show sga; Total
System Global Area 147615836 bytes Fixed Size 282716 bytes Variable Size 113246208
bytes Database Buffers 33554432 bytes Redo Buffers 532480 bytes SQL> show
parameter spfile NAME TYPE VALUE ------------------------------------ -----------
------------------------------ spfile string %ORACLE_HOME%DATABASESPFILE%
ORACLE_SID%.ORA SQL> create pfile from spfile; File created. SQL> alter system
set sga_max_size=20m scope=spfile; System altered. SQL> shutdown immediate;
Database closed. Database dismounted. ORACLE instance shut down. SQL> startup ORA-
03113: end-of-file on communication channel
Oracle 11g: What Happens When Setting SGA_MAX_SIZE less
than SGA_TARGET? April 14, 2011No comments
Have you ever hosed up your memory parameters such that you cannot get Oracle to even enter
the startup nomount state?
Here I’ll do just that by setting sga_max_size to a value less than sga_target, and then trying to
start the database.
First a sanity check so you can see the memory parameters. In this case I am using ASMM
(automatic shared memory management), and not the new 11g AMM (automatic memory
management) features.
sqlplus / as sysdba
SQL> show parameter memory_max_target
NAME TYPE VALUE
------------------------------------ ----------- -------------------------
-----
memory_max_target big integer 0
SQL> show parameter sga_max_size
NAME TYPE VALUE
------------------------------------ ----------- -------------------------
-----
sga_max_size big integer 1056M
SQL> show parameter sga_target
NAME TYPE VALUE
------------------------------------ ----------- -------------------------
-----
sga_target big integer 1G
SQL> show parameter pga_aggregate_target;
NAME TYPE VALUE
------------------------------------ ----------- -------------------------
-----
pga_aggregate_target big integer 350M
OK, let’s have some fun. We’ll set our parameters to something that doesn’t make sense by
setting sga_max_size to 0. Then we’ll shutdown immediate.
SQL> alter system set sga_max_size=0 scope=spfile;
System altered.
SQL> shutdown immediate;
Database closed.
Database dismounted.
ORACLE instance shut down.
Now we’ll start our DB back up…and notice that we cant! Panic! We get the ORA-00823 error.
SQL> startup;
ORA-01078: failure in processing system parameters
ORA-00823: Specified value of sga_target greater than sga_max_size
Uh oh…not even a nomount works. Makes sense though. Nomount reads the pfile and allocates the
memory for the instance, so no wonder it is failing there if we can’t properly allocate memory. I
guess we can’t just fire this thing into nomount state and run our alter system commands.
SQL> startup nomount
ORA-01078: failure in processing system parameters
ORA-00823: Specified value of sga_target greater than sga_max_size
OK, no sweat. I’ll create my text based pfile from the spfile, edit this and be on my way.
SQL> create pfile from spfile;
create pfile from spfile
*
ERROR at line 1:
ORA-01565: error in identifying file '?/dbs/spfile@.ora'
ORA-27037: unable to obtain file status
Linux-x86_64 Error: 2: No such file or directory
Additional information: 3
Huh? Where’s my spfile? Can you feel the hairs stand on the back of you neck as the panic sets in
that your DB is hosed? No worried, the spfile has to be there somewhere. After all, this was a
previously running system. Let’s looks in the alert.log for how my instance booted previously.
cd /u01/app/oracle/diag/rdbms/orcl/orcl/trace
vi alert_orcl.log
A quick scan through the alert log reveals that there is indeed an spfile somewhere out in the
universe:
spfile = "+DATA/orcl/spfileorcl.ora"
Ahh, that’s right. This instance is using ASM (automatic storage management). To create that pfile
I need to tell the command exactly where that spfile is:
SQL> create pfile from spfile='+DATA/orcl/spfileorcl.ora';
File created.
Now we’re cooking! There’s the init.ora file we need:
[oracle@localhost dbs]$ cd $ORACLE_HOME/dbs
[oracle@localhost dbs]$ ls -lart initorcl.ora
-rw-r----- 1 oracle oinstall 1061 Apr 14 09:20 initorcl.ora
And we happily edit it in vi and change sga_max_size=0 to sga_max_size=1056M
Now our instance starts!
SQL> startup nomount pfile='$ORACLE_HOME/dbs/initorcl.ora';
ORACLE instance started.
Total System Global Area 1102344192 bytes
Fixed Size 2212576 bytes
Variable Size 335547680 bytes
Database Buffers 754974720 bytes
Redo Buffers 9609216 bytes
Overwrite our spfile with the new values from our pfile:
SQL> create spfile='+DATA/orcl/spfileorcl.ora' from pfile;
File created.
And then shutdown the database and restart. Voila, everything is back to life:
SQL> shutdown;
ORA-01507: database not mounted
ORACLE instance shut down.
SQL> startup;
ORACLE instance started.
Total System Global Area 1102344192 bytes
Fixed Size 2212576 bytes
Variable Size 335547680 bytes
Database Buffers 754974720 bytes
Redo Buffers 9609216 bytes
Database mounted.
Database opened.
ga_target vs sga_max_size
SGA_TARGET specifies the total size of all SGA components. If the SGA_TARGET is set,
then the following memory pools are automatically sized :
Buffer cache (DB_CACHE_SIZE)
Shared pool (SHARED_POOL_SIZE)
Large pool (LARGE_POOL_SIZE)
Java pool ( JAVA_POOL_SIZE)
SGA_MAX_SIZE specifies the hard limit upto which the SGA_TARGET can dynamically
grow. While executing DBCA, Oracle suggests that the estimated SGA_MAX_SIZE is to
set aside 40% of memory. However, it should be set according to your requirement that
depends on multiple factors such as no of concurrent users, volume of transactions and
growth rate of database. Under normal operation, you can set the SGA_MAX_SIZE
equals to the SGA_TARGET. Sometimes, we need to perform some extra-heavy batch
processing jobs that leads to more SGA size. At this circumstance, you must have
capability to adjust for peak loads. That is why, you set hard limit for your
SGA_MAX_SIZE.
SGA_MAX_SIZE cannot be changed dynamically without bouncing the database whereas
SGA_TARGET can be changed dynamically without bouncing the database.
If you try to modify SGA_MAX_SIZE dynamically, you will get an error of
ORA-02095: specified initialization parameter cannot be modified.
SGA_TARGET can never be greater than SGA_MAX_SIZE. If you try to set the
SGA_TARGET to a value which is greater than that of SGA_MAX_SIZE, then Oracle will
throw an error of
ORA-02097: parameter cannot be modified because specified value is invalid
ORA-00823: specified value of SGA_TARGET greater than SGA_MAX_SIZE.
If the SGA_MAX_SIZE is not set and the SGA_TARGET is set, then the SGA_MAX_SIZE
takes the value of SGA_TARGET.
If you set the SGA_MAX_SIZE greater than your server memory capacity and bounce the
database, you will get an error of
ORA-27102 : out of memory
SVR4 Error : 12 : not enough space
Memory Tuning - How OS Page Sizes Can Impact Oracle
Performance Theory
Modern operating systems provide each process it's own virtual address space that is potentially
larger than physical memory. It does this by mapping the virtual addresses onto actual physical
memory pages. The following diagram shows how large virtual address spaces are mapped onto
small physical memory.
The virtual to physical relationship is maintained in mapping tables. Linux maintains a separate map
for each process. The map contains one entry for each page where the size of the page is set by the
operating system. The CPU attempts to speed up the mapping of virtual memory to physical
addresses by caching a subset of the mapping entries in its internal cache. Modern large memory
systems and the resulting large processes have increased the size of memory mapping tables faster
than the cpu cache sizes have increased. The processor cache is usually very small with only maybe
100 entries in may processors. This mismatch causes faults that can have significant performance
implications.
System Analysis
Linux uses physical memory to maintain the process memory mapping tables and swaps those
mapping tables in and out of the processor cache on context switches and on memory page table
faults. This physical memory is unavailable for other uses essentially reducing the amount of memory
available to the rest of the system. The amount of memory used for page tables is the sum of all the
virtual process sizes / the page table size multiplied by the size of a page table entry. So a system
with a 20GB Oracle SGA uses 50MB of physical memory for page tables just for the SGA:
20GB Process Size / 4K page size * 10 = 50Megabytes. (5 million
entries)
Every connection to an Oracle database runs in its own process that has direct access to the Oracle
DB through shared memory. This doesn't seem too bad until you consider that page tables for the
entire shared memory space are duplicated across each process. So a 20GB Oracle process with
200 database connections would 5GB for the page tables just for the SGA portion of each process:
20GB Process Size/ 4K page size * 10 entry size * 200 connections =
10GB. (1 Billion page table entries)
This means a 32GB Oracle server with a 20GB SGA and 200 connections uses 30% of the physical
memory just for the page tables. It also means that the oracle processes, the OS and other
processes no longer fit into memory resulting in possibly significant paging. You cannot rely
on ps commands or other process monitorswhen investigating this because Linux always uses all
available memory allocating any "extra" to file system buffers and other needs. You can get your
actual page table usage in your system by dumping the contents of /etc/procinfo with cat
/etc/procinfo.
Linux provides the ability to change the page size from 4KB to 2MB potentially returning large
amounts of memory to the swappable pool. Calculations show that converting just the Oracle SGA in
the previous example would save almost 10GB.
20GB Process size / 2MB page size * 10 entry size * 200 connections =
20MB (2 million entries)
Why Aren't Huge Pages the Default?
Huge (2MB) pages are different from the normal 4K pages in that they are locked into memory and do
not swap. This means that extreme care must be taken when selecting the number and size of the
huge page space. The Huge Page space should be large enough to hold the Oracle SGA while
leaving enough other memory to run the non-SGA client code, the operating system and other
processes. Teams must understand their memory needs so that htey can set the correct number of
huge pages.
Production Example
I was talking with a colleague about their system and we did some back of the napkin calculations.
They had an Oracle RAC with two 72GB servers each with 500 database connections. This ran a little
slower than expected when both machines were up but their real problem was that they were unable
to fail over to a single node even though they had plenty of CPU capacity. The following calculations
show why.
Before
Page Table Entries (SGA) = 35GB / 4KB = 8.75MB
Page Table Entries (1000 connections) = 1000 * 8.75MB = 8.75GB
Memory (1000 connections) = 10B * 8.75G = 87.5GB
After
Page Table Entries (SGA) = 35GB / 2MB = 17.5KB
Page Table Entries (1000 connections) = 1000 * 17.5KB = 17.5MB
Memory (1000 connections) = 10B * 17.5M = 175MB
The team converted 35GB of memory to Huge Pages so that the entire SGA fit into the huge pages.
This returned 40GB of free memory to each machine and made it possible fall back to a single
machine when they had planned or unplanned outages on a single server.
A smaller system at another site recovered 7GB of physical memory on their 32GB servers by
converting their 20GB oracle SGA to Huge Pages. This ended all their system paging.
Recap
Intelligent conversion from small memory pages to large memory pages modern modern large RAM
systems can have significant performance implications:
Larger page sizes result in fewer page table entries in the CPU cache. This results in fewer cache misses and less CPU stalling.
The memory savings resulting from the 1/500 reduction in page table entries is multiplied by the number of processes sharing the same shared memory.
Every team with large Oracle Databases should investigate the use of Huge Pages no matter what
their operating system.
Configuring HugePages for Oracle on Linux (x86-64)
For large SGA sizes, HugePages can give substantial benefits in virtual memory management. Without HugePages, the memory of the SGA is divided into 4K pages, which have to be managed by the Linux kernel. Using HugePages, the page size can be increased to anything between 2MB and 256MB, thereby reducing the total number of pages to be managed by the kernel and therefore reducing the amount of memory required to hold the page table in memory. In addition to these changes, the memory associated with HugePages can not be swapped out, which forces the SGA to stay memory resident. The savings in memory and the effort of page management make HugePages pretty much mandatory for Oracle 11g systems running on x86-64 architectures.
Note. Automatic Memory Management (AMM) is not compatible with HugePages, so apart from ASM instances and small unimportant databases, you will probably have no need for AMM on a real system. Instead, Automatic Shared Memory Management and Automatic PGA Management should be used as they are compatible with HugePages.
Run the following command to determine the current HugePage usage. The default HugePage size is 2MB on Oracle Linux 5.x and as you can see from the output below, by default no HugePages are defined.
$ grep Huge /proc/meminfo
HugePages_Total: 0
HugePages_Free: 0
HugePages_Rsvd: 0
HugePages_Surp: 0
Hugepagesize: 2048 kB
$
Depending on the size of your SGA, you may wish to increase the value of Hugepagesize.
Create a file called "hugepages_setting.sh" with the following contents.
#!/bin/bash
#
# hugepages_settings.sh
#
# Linux bash script to compute values for the
# recommended HugePages/HugeTLB configuration
#
# Note: This script does calculation for all shared memory
# segments available when the script is run, no matter it
# is an Oracle RDBMS shared memory segment or not.
# Check for the kernel version
KERN=`uname -r | awk -F. '{ printf("%d.%d\n",$1,$2); }'`
# Find out the HugePage size
HPG_SZ=`grep Hugepagesize /proc/meminfo | awk {'print $2'}`
# Start from 1 pages to be on the safe side and guarantee 1 free HugePage
NUM_PG=1
# Cumulative number of pages required to handle the running shared memory
segments
for SEG_BYTES in `ipcs -m | awk {'print $5'} | grep "[0-9][0-9]*"`
do
MIN_PG=`echo "$SEG_BYTES/($HPG_SZ*1024)" | bc -q`
if [ $MIN_PG -gt 0 ]; then
NUM_PG=`echo "$NUM_PG+$MIN_PG+1" | bc -q`
fi
done
# Finish with results
case $KERN in
'2.4') HUGETLB_POOL=`echo "$NUM_PG*$HPG_SZ/1024" | bc -q`;
echo "Recommended setting: vm.hugetlb_pool = $HUGETLB_POOL" ;;
'2.6') echo "Recommended setting: vm.nr_hugepages = $NUM_PG" ;;
*) echo "Unrecognized kernel version $KERN. Exiting." ;;
esac
# End
Make the file executable.
$ chmod u+x hugepages_setting.sh
Make sure all the Oracle services are running as normal on the server, then run the script and make a note of the recommended "vm.nr_hugepages" value.
$ ./hugepages_settings.sh
Recommended setting: vm.nr_hugepages = 191
$
Edit the "/etc/sysctl.conf" file as the "root" user, adding the following entry, adjusted based on your output from the script. You should set the value greater than or equal to the value displayed by the script. You only need 1 or 2 spare pages.
vm.nr_hugepages=192
Run the following command as the "root" user.
# sysctl -p
You can now see the HugePages have been created, but are currently not being used.
$ grep Huge /proc/meminfo
HugePages_Total: 192
HugePages_Free: 192
HugePages_Rsvd: 0
HugePages_Surp: 0
Hugepagesize: 2048 kB
$
Add the following entries into the "/etc/security/limits.conf" script, where the setting is the size of the HugePages allocation in KB (HugePages * Hugepagesize * 1024).
* soft memlock 393216
* hard memlock 393216
Check the MEMORY_TARGET parameters are not set for the database and SGA_TARGET and PGA_AGGREGATE_TARGET parameters are being used instead.
SQL> show parameter target
NAME TYPE VALUE
------------------------------------ ----------- --------------------------
----
archive_lag_target integer 0
db_flashback_retention_target integer 1440
fast_start_io_target integer 0
fast_start_mttr_target integer 0
memory_max_target big integer 0
memory_target big integer 0
parallel_servers_target integer 16
pga_aggregate_target big integer 125M
sga_target big integer 376M
SQL>
Restart the server and restart the database services as required.
Check the HugePages information again.
$ grep Huge /proc/meminfo
HugePages_Total: 192
HugePages_Free: 52
HugePages_Rsvd: 49
HugePages_Surp: 0
Hugepagesize: 2048 kB
$