Come sappiamo, sui sistemi Linux a 32 bit la quantità di memoria massima allocabile per la SGA è di circa 1.7 GB.
Con i kernel enterprise di Red Hat o Oracle Enterprise Linux è possibile "vedere" tutta la memoria installata anche oltre i 4 GB grazie al PAE (physical address extension), che utilizza 36 bit per indirizzare la memoria. In questo modo si possono vedere fino a 64 GB di RAM, utilizzandoli per la block buffer cache. Ogni processo può vedere fino a 4 GB di RAM.
Per usare VLM su Linux bisogna utilizzare una sorta di memory filesystem, chiamato shmfs, ramfs o tmpfs a seconda delle versioni di Linux; tutti questi filesystem sono implementati grazie a PAE.
Allocando una SGA molto grande, è possibile però che ci sia anche un overhead di gestione delle pagine di memoria da parte del kernel; di default infatti la RAM viene gestita in pagine da 4 KB utilizzando una tabella, la page table, che può diventare molto grande (anche centinaia di MB) e rallentare il sistema durante la traduzione da indirizzi virtuali a indirizzi fisici.
I kernel Linux, analogamente ad altri, forniscono la possibilità di utilizzare le hugepage, ovvero delle pagine di RAM che vanno da 2 MB a 256 MB a seconda della versione del kernel. Personalmente ho constatato che RHEL5 ha hugepage da 2 MB.
Altri vantaggi delle hugepages: non sono swappabili, eliminano il lookup delle pagetable, sono più veloci da gestire per il kernel, non vengono considerate da kswapd.
Su Linux 32 bit viene usato il parametro USE_INDIRECT_DATA_BUFFERS=TRUE,e quindi usato uno dei memory filesystem (generalmente tmpfs nelle versioni recenti di Linux, quello che compare col comando df).
Viene persa però l'allocazione dinamica delle componenti della SGA tramite i parametri DB_CACHE_SIZE e SGA_TARGET, che devono essere rimossi; si torna quindi al vecchio DB_BLOCK_BUFFERS, che è il numero di blocchi di cache da allocare.
Su Linux a 64 bit non ci sono queste limitazioni: la RAM viene allocata direttamente e quindi l'unica differenza è nella dimensione delle pagine. La differenza maggiore è che non è possibile utilizzare l'Automatic Memory Management di 11g (AMM), poiché esso a sua volta utilizza dei file su tmpfs per allocare la memoria. Per utilizzare le hugepage bisogna quindi disabilitare i parametri MEMORY_TARGET e MEMORY_MAX_TARGET.
Una particolarità: AMM utilizza solo tmpfs perché deve espandere e ridurre dinamicamente l'allocazione dei file, cosa possibile solo con un filesystem "temporaneo" come tmpfs e impossibile invece con ramfs. Si può fare un'analogia con i file temporanei (tempfile) nei filesystem, ad esempio quelli utilizzati per i tablespace temporanei.
Vediamo come configurare un sistema a 32 bit con 8 GB di RAM e una SGA più grande di 1.7 GB.
Nell'fstab, con un'installazione di default di Red Hat 5, di trova tmpfs:
tmpfs /dev/shm tmpfs defaults 0 0
tmpfs deve essere poi scrivibile dall'utente oracle, quindi bisogna impostare i permessi corretti mediante chmod o chown direttamente.
Bisogna innalzare il limite della memoria locked in /etc/security/limits.conf:
oracle soft memlock 5529600
oracle hard memlock 5529600
I numeri rappresentano il massimo spazio di indirizzi locked-in-memory, in KB. I valori dipendono dalla RAM installata e dalle dimensioni massime della SGA che si intende allocare.
Ricordiamo che nel memory filesystem finiscono i database buffers, ovvero viene allocato un file di db_block_buffers*db_block_size byte.
Le hugepage devono essere riservate in fase di boot del kernel tramite il parametro vm.nr_hugepages. Oracle fornisce un utilissimo script per calcolare il numero delle hugepage da riservare; vedere il documento MOS 401749.1.
In pratica bisogna fare partire l'istanza con i valori di db_block_buffers, shared_pool_size, large_pool_size e quant'altro già impostati per sfruttare tutta la RAM ragionevolmente disponibile, e poi lo script sommerà il numero di hugepage necessarie per coprire il fabbisogno, più qualche hugepage extra per essere sicuri che siano sufficienti.
Nel mio caso:
java_pool_size = 32M
large_pool_size = 16M
shared_pool_size = 1504M
streams_pool_size = 16M
db_block_buffers = 320000
Quindi la parte di buffer cache della SGA sarà pari a 2621440000 bytes (2500 MB). Dopo avere avviato l'istanza verifichiamo l'utilizzo del ramfs:
$ ls -l /dev/shm/
total 2560000
-rw-r----- 1 oracle dba 2621440000 Oct 25 21:16 ora_TESTDB_786437
Lo script ha calcola vm.nr_hugepages = 837. Il parametro è attivo solo dopo avere fatto il reboot.
All'avvio successivo è possibile vedere la situazione delle hugepage nel file /proc/meminfo (da controllare):
HugePages_Total: 837
HugePages_Free: 0
HugePages_Rsvd: 0
Hugepagesize: 2048 kB
Una volta avviata l'istanza, le hugepage vengono riservate e allocate:
HugePages_Total: 837
HugePages_Free: 568
HugePages_Rsvd: 565
È una strana notazione: le pagine vengono riservate all'avvio dell'istanza e diminuiscono man mano che la memoria viene occupata dai dati nella buffer cache.
Nella memoria "normale" rimangono i shared segments della shared pool e di ASM (nel mio caso):
$ ipcs -m
------ Shared Memory Segments --------
key shmid owner perms bytes nattch status
0xb0af65c0 131075 oracle 600 85983232 12
0xb6c83f68 753668 oracle 600 1663041536 52





