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?
- memory_max_target auf einen Wert setzen, so dass für beide Bereiche (ASM und Datenbank) ausreichend Platz ist.
- 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