Blog 
Automatic Memory Management – alles super, oder was?

Wie aus meinen letzten Blogs schon bekannt, habe ich meine für meine Tests Oracle 10g und 11g auf Oracle Linux 6 Update 1 aufgebaut – soweit so gut. Auch wenn es hierfür keinen offiziellen Support von Oracle gibt, funktioniert das ganz gut. Aufgrund eines aktuellen Vortrages habe ich Tests mit dem Oracle Memory Management unter Oracle 11g gemacht und dabei sind mir ein paar Dinge aufgefallen, die ich an dieser Stelle gerne weitergeben möchte:

SPFILE im ASM

Wie sicherlich bekannt, kann das Memory für SGA und PGA in Oracle 11g mit dem Parameter memory_target bzw. memory_max_target verwaltet werden. Für meine Tests habe ich also beschlossen, den Instanzen etwas mehr Memory (2GB) zur Verfügung zu stellen.

SQL> ALTER SYSTEM SET memory_max_target = 2G scope=spfile sid='*';

System altered.

% srvctl stop database -d ORASE
% srvctl start database -d ORASE
PRCR-1079 : Failed to start resource ora.racvm1.db CRS-5017: The resource action "ora.racvm1.db start" encountered the following error: ORA-00845: MEMORY_TARGET not supported on this system .
For details refer to "(:CLSN00107:)" in "/u01/app/grid/11.2.0/grid/log/obelix/agent/crsd/oraagent_oracle/oraagent_oracle.log".
STARTUP WARNING: You are trying to use the MEMORY_TARGET feature.
This feature requires the /dev/shm file system to be mounted for at least 2097152000 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 1866305536 and used is 208990208 bytes. Ensure that the mount point is /dev/shm for this directory. 
memory_target needs larger /dev/shm.

Wahrscheinlich kennen Sie den Fehler und wissen, dass es sich einfach um die neue Shared-Memory Verwaltung handelt (siehe auch Abschnitt 2). In der Alert-Datei finden wir ein paar nähere Hinweise:

WARNING: You are trying to use the MEMORY_TARGET feature. This feature requires the /dev/shm file system to be mounted for at least 2147483648 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 1866305536 and used is 208990208 bytes. Ensure that the mount point is /dev/shm for this directory.

Dummerweise hatte ich auch nicht bedacht, dass ja das ASM selbst auch noch einen Anteil des Shared-Memories benötigt, insofern reichen 2 GB nicht aus. Aber was jetzt?

  1. memory_max_target auf einen Wert setzen, so dass für beide Bereiche (ASM und Datenbank) ausreichend Platz ist.
  2. Shared-Memory Bereich vergrößern.

Zu Punkt 1 kann ich derzeit nur sagen: „Dumm gelaufen!“ Wie soll man den Parameter ändern, wenn man die Instanz nicht starten kann? Da sich das spfile im ASM befindet, klappt ein „CREATE pfile= … FROM spfile“ nicht. Editieren der Datei ist auch nicht möglich. Vielleicht hat ja jemand von Ihnen einen Tipp, wie man nachträglich das spfile auslesen bzw. ändern kann. Also als Tipp: 1. Vor der Änderung von Parametern immer eine Kopie des spfiles erstellen:

SQL> CREATE pfile='/tmp/initRAC.ora' FROM spfile;

2. Bei RAC möglichst eine Instanz nach der anderen ändern und nicht alle gleichzeitig. Mir blieb also nichts weiter übrig, als das Shared-Memory zu vergrößern.

Posix-Style Shared Memory Management

Wie wahrscheinlich hinlänglich bekannt, wird, wenn man in Oracle 11g mit dem Automatic Management arbeitet, d.h. memory_target bzw. memory_max_target nutzt, statt der alten System-V Shared Memory Verwaltung der so genannte Posix-Style gewählt. Der Grund ist, dass ja mit memory_target sowohl der Bereich für die SGA als auch PGA dynamisch angepasst werden kann. Patrick Schwanke hat in seinem Dokument „Speicherverwaltung in Oracle 11g“ die Verwendung bzw. Hintergründe dazu erklärt. Um meinen Instanzen jetzt die 2 GB Memory geben zu können, habe ich den Parameter für „tmpfs“ in der /etc/fstab entsprechend angepasst. Der Eintrag sieht wie folgt aus:

shmfs      /dev/shm    tmpfs   size=3g        0 0

Da ich noch einen Teil für das ASM brauche, war ich an dieser Stelle etwas großzügiger und habe direkt 3 GB gewählt. Um sicherzugehen, dass der Parameter auch wirklich funktioniert, habe ich dann einfach das System durchgestartet und siehe da …

# df -k Filesystem           1K-blocks      Used Available Use% Mounted on
/dev/mapper/vg_..._root      26391624   16380736   8670268  66% /
tmpfs                         2026656    1267368   759288   63% /dev/shm
/dev/sda1                      495844      50942    419302  11% /boot

Wie unschwer zu erkennen, ist der Shared-Memory-Bereich keine 3 GB gross, sondern in etwa 2 GB, und damit genau so groß wie vorher. Bei Oracle konnte ich keine Hilfe erwarten, da Linux 6 offiziell nicht unterstützt wird, aber wofür gibt es denn google! Abhilfe schafft einzig eine Änderung in der Datei /etc/rc.d/rc.sysinit: Hier muss folgender Eintrag geändert werden:

Vorher:  mount -f /dev/shm >/dev/null 2>&1 
Nachher: mount /dev/shm >/dev/null 2>&1

Danach wird der Parameter, der in der Datei /etc/fstab steht, auch tatsächlich genommen – keine Ursache, große Wirkung! Danach können die Instanzen problemlos gestartet werden.

3.  Zuweisung des Memories

Mit dem Parameter memory_max_target wird nur eine Obergrenze für das Shared-Memory einer Instanz festgelegt. Beim Starten wird geprüft, ob dieser Bereich bei Bedarf zur Verfügung stände, er wird jedoch nicht allokiert. Die tatsächliche Größe wird durch memory_target angegeben. Dieser kann im laufenden Betrieb vergrößert (bis memory_max_target) oder verkleinert werden, wenn es die einzelnen Bereiche zulassen (was meist nicht der Fall ist!).

SQL> ALTER SYSTEM SET MEMORY_TARGET=2000M sid='ORASE1';

Jetzt können die einzelnen Caches automatisch oder manuell entsprechend vergrößert werden. Eine Abfrage von v$sgainfo zeigt:

SQL> select * from v$sgainfo;

NAME                                  BYTES RES
-------------------------------- ---------- ---
Fixed SGA Size                      2229944 No
Redo Buffers                        5173248 No
Buffer Cache Size                 352321536 Yes
Shared Pool Size                  385875968 Yes
Large Pool Size                    16777216 Yes
Java Pool Size                     16777216 Yes
Streams Pool Size                         0 Yes
Shared IO Pool Size                       0 Yes
Granule Size                       16777216 No
Maximum SGA Size                 2087780352 No
Startup overhead in Shared Pool   137554960 No
Free SGA Memory Available        1308622848

Okay, der „neue“ Bereich steht als „Free SGA Memory“ zur Verfügung, genau so sollte es sein. Ein paar Tests später fällt auf, dass sich weder der Shared-Pool noch der Buffercache wesentlich vergrößert hat. Also werde ich einfach explizit den Buffercache vergrößern.

SQL> ALTER SYSTEM SET db_cache_size=900M sid='ORASE1';

 ALTER SYSTEM SET db_cache_size=900M sid='ORASE1'
*
ERROR at line 1: ORA-02097: parameter cannot be modified because
specified value is invalid ORA-00384: Insufficient memory to grow cache

Wieso das? Der Name „Free SGA Memory Available“ in v$sgainfo ist missverständlich, da es sich dabei nicht um tatsächlich freien Speicher, sondern um die PGA handelt.

SQL> SELECT * from v$pgastat
     WHERE name LIKE '%target parameter%';
NAME                              VALUE      UNIT
--------------------------------  ---------- ------------
aggregate PGA target parameter    1308622848 bytes

Doch wie gibt man die PGA jetzt frei?

 SQL> alter system set pga_aggregate_target=200M;

Den Befehl darf man gerne benutzen, allerdings sollte man beachten, dass bei der Verwendung von Automatic Memory Management (gilt auch für Oracle 10g), die eingestellten Werte Untergrenzen darstellen. In diesem Fall wird also die Untergrenze für die PGA auf 200 MB gesetzt, auf den derzeitigen Wert von fast 1,3 GB hat das keinen Einfluss. Einzige Möglichkeit ist, zunächst die SGA zu vergrößern, danach kann der Buffercache bei Bedarf angepasst werden. Der allokierte Bereich wird zunächst dem Buffercache zugewiesen.

SQL> ALTER SYSTEM SET sga_target=1500M sid='ORASE1';

System altered.

SQL> SELECT * FROM v$sgainfo;

NAME                                  BYTES RES
-------------------------------- ---------- ---
Fixed SGA Size                      2229944 No
Redo Buffers                        5173248 No
Buffer Cache Size                1140850688 Yes
Shared Pool Size                  385875968 Yes
Large Pool Size                    16777216 Yes
Java Pool Size                     16777216 Yes
Streams Pool Size                         0 Yes
Shared IO Pool Size                       0 Yes
Granule Size                       16777216 No
Maximum SGA Size                 2087780352 No
Startup overhead in Shared Pool   137554960 No
Free SGA Memory Available         520093696

Damit habe ich nach einigem „Trial & Error“ endlich das gewünschte Ergebnis.

4. Empfehlung

Neben den Empfehlung, bei Änderungen der Parameter vorher ein Backup zu machen, hat sich in der Praxis herausgestellt, dass in produktive Umgebungen  Untergrenzen für die Caches (zumindest Shared-Pool und Buffercache) gesetzt werden sollten. Dadurch wird verhindert, dass durch ungünstig geschriebene Anwendungen die Performance des Systems leidet. In einem Projekt, in dem ich vor kurzen ein Performance Tuning durchgeführt habe, war die PGA 3 GB groß, der Shared-Pool ca 1,5 GB und für den Buffercache standen nur noch 500 MB zur Verfügung. Sicherlich nicht ganz optimal.

memory_max_target    = 3G
memory_target        = 2G
db_cache_size        = 1G
shared_pool_size     = 500M
pga_aggregate_target = 200M

In diesem Fall werden aktuell 2 GB auf die verschiedenen Caches verteilt, wobei für den Buffercache mindestens 1 GB, für den Shared-Pool 500 MB und für die PGA 200 MB verwendet werden. Also stehen grob 300 MB als „Spielmasse“ zur Verfügung. Die unterschiedlichen Werte von memory_target und memory_max_target machen dann Sinn, wenn man mehrere Datenbanken auf einem Server betreibt. Über die Änderung von memory_target kann dann einer Instanz temporär mehr Memory gegeben werden (z.B. für einen Batchlauf), ohne die Instanz durchstarten zu müssen. Viel Erfolg beim Ausprobieren und über Hinweise und Anmerkungen würde ich mich sehr freuen – und über einen Tipp, wie man ein spfile im ASM ändert. Und wenn Sie mir mir Kontakt aufnehmen möchten und Beratung zu weiteren Oracle Themen brauchen: www.carajandb.com

Keine Kommentare zu “Automatic Memory Management – alles super, oder was?

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert

Was kann CarajanDB für Sie tun?