1. Database Strategy/
  2. Oracle/

Oracle su Linux: i parametri kernel che nessuno configura

Ivan Luminaria
Ivan Luminaria
DWH Architect · Project Manager · Oracle DBA & Performance Tuning · PL/SQL Senior & Mentor

Il cliente era una società di logistica con un Oracle 19c Enterprise Edition su Oracle Linux 8. Sessanta utenti concorrenti, un gestionale custom, circa 400 GB di dati. Il server era un Dell PowerEdge con 128 GB di RAM e 32 core.

Le lamentele erano vaghe ma persistenti: “Il sistema è lento.” “Le query del mattino ci mettono il doppio rispetto a due mesi fa.” “Ogni tanto si blocca tutto per qualche secondo.”

Quando sono entrato sul server, la prima cosa che ho verificato non è stata il database. È stato il sistema operativo.

cat /proc/meminfo | grep -i huge
sysctl vm.nr_hugepages
cat /sys/kernel/mm/transparent_hugepage/enabled

Risultato: zero Huge Pages configurate, Transparent Huge Pages attive, parametri kernel tutti ai valori di default. L’installazione di Oracle era stata fatta col wizard, il sistema operativo non era stato toccato.

Ecco il problema. Non era Oracle. Era Linux che non era stato preparato per Oracle.


🔍 La diagnosi #

Prima di cambiare qualsiasi cosa, ho misurato lo stato attuale. Servono numeri, non impressioni.

# Stato della SGA
sqlplus -s / as sysdba <<SQL
SELECT name, value/1024/1024 AS mb
FROM   v$sgainfo
WHERE  name IN ('Maximum SGA Size', 'Free SGA Memory Available');
SQL

# Utilizzo memoria del sistema
free -h

# Parametri kernel correnti
sysctl -a | grep -E "kernel.sem|kernel.shm|vm.nr_hugepages|vm.swappiness"

# I/O scheduler in uso
cat /sys/block/sda/queue/scheduler

# Limiti utente oracle
su - oracle -c "ulimit -a"

Ecco cosa ho trovato:

ParametroValore attualeValore raccomandato
SGA Target64 GB64 GB (ok)
vm.nr_hugepages033280
Transparent Huge Pagesalwaysnever
vm.swappiness601
kernel.shmmax33554432 (32 MB)68719476736 (64 GB)
kernel.shmall209715216777216
kernel.sem250 32000 100 128250 32000 100 256
I/O schedulermq-deadlinedeadline (ok)
oracle nofile102465536
oracle nproc409616384
oracle memlock65536 KBunlimited

Quasi tutto era sbagliato. Non per errore — per omissione. Nessuno si era preso la briga di configurare il sistema operativo dopo l’installazione.


📦 Huge Pages: il parametro che cambia tutto #

Le Huge Pages sono il singolo parametro più impattante per Oracle su Linux. E sono anche quello che viene ignorato più spesso.

Perché servono #

Di default, Linux gestisce la memoria in pagine da 4 KB. Un’SGA da 64 GB significa circa 16,7 milioni di pagine. Ogni pagina ha una entry nella Page Table, e il sistema deve tradurre indirizzi virtuali in fisici per ciascuna. Il TLB (Translation Lookaside Buffer) della CPU può memorizzare solo poche migliaia di traduzioni — il resto viene gestito dalla MMU, che è lenta.

Le Huge Pages sono pagine da 2 MB. La stessa SGA da 64 GB diventa 32.768 pagine. Il TLB regge, la pressione sulla MMU crolla, le performance migliorano.

Come configurarle #

Ho calcolato il numero di Huge Pages necessarie:

# SGA = 64 GB = 65536 MB
# Ogni Huge Page = 2 MB
# Pagine necessarie = 65536 / 2 = 32768
# Aggiungo un 1.5% di margine → 33280

echo "vm.nr_hugepages = 33280" >> /etc/sysctl.d/99-oracle.conf
sysctl -p /etc/sysctl.d/99-oracle.conf

Verifica:

grep -i huge /proc/meminfo

Output atteso:

HugePages_Total:   33280
HugePages_Free:    33280
HugePages_Rsvd:        0
Hugepagesize:       2048 kB

Dopo il riavvio dell’istanza Oracle, la SGA viene allocata nelle Huge Pages:

HugePages_Total:   33280
HugePages_Free:      512
HugePages_Rsvd:      480

La differenza è misurabile: le latch free wait e i library cache contention si riducono drasticamente.


🧱 Shared memory e semafori #

Oracle usa la shared memory del kernel per la SGA. Se i limiti sono troppo bassi, l’istanza non riesce ad allocare la memoria richiesta — o peggio, frammenta l’allocazione.

cat >> /etc/sysctl.d/99-oracle.conf << 'SYSCTL'
# Shared memory
kernel.shmmax = 68719476736
kernel.shmall = 16777216
kernel.shmmni = 4096

# Semaphores: SEMMSL SEMMNS SEMOPM SEMMNI
kernel.sem = 250 32000 100 256
SYSCTL

sysctl -p /etc/sysctl.d/99-oracle.conf
ParametroSignificatoValore
shmmaxDimensione massima di un singolo segmento di shared memory64 GB
shmallPagine totali di shared memory allocabili64 GB in pagine da 4K
shmmniNumero massimo di segmenti di shared memory4096
semSEMMSL, SEMMNS, SEMOPM, SEMMNI250 32000 100 256

Queste impostazioni non sono valori magici. Sono dimensionate sulla SGA del database. Se l’SGA cambia, i parametri vanno ricalcolati.


💾 I/O Scheduler #

Il default su RHEL/Oracle Linux 8 con device NVMe è none o mq-deadline. Per i dischi SAS/SATA tradizionali, il default potrebbe essere bfq o cfq.

Per Oracle, la raccomandazione è deadline (o mq-deadline sui kernel più recenti):

# Verifica corrente
cat /sys/block/sda/queue/scheduler

# Se non è deadline/mq-deadline, impostarlo
echo "deadline" > /sys/block/sda/queue/scheduler

# Per renderlo permanente via GRUB
grubby --update-kernel=ALL --args="elevator=deadline"

cfq (Completely Fair Queuing) è pensato per workload desktop — distribuisce equamente l’I/O tra i processi. Ma Oracle non ha bisogno di equità: ha bisogno che le richieste I/O vengano servite nell’ordine che minimizza i seek. deadline fa esattamente questo.


🚫 Disabilitare Transparent Huge Pages #

Questo è il parametro più insidioso. Le Transparent Huge Pages (THP) sono una funzione del kernel che sembra una buona idea: il kernel promuove automaticamente le pagine normali a pagine grandi.

Per Oracle è un disastro. Il processo khugepaged lavora in background per compattare le pagine, causando latenze imprevedibili — quei “blocchi di qualche secondo” che il cliente lamentava.

Oracle lo dice esplicitamente nella documentazione: disabilitare THP.

# Verifica stato corrente
cat /sys/kernel/mm/transparent_hugepage/enabled
# Output tipico: [always] madvise never

# Disabilitare a runtime
echo never > /sys/kernel/mm/transparent_hugepage/enabled
echo never > /sys/kernel/mm/transparent_hugepage/defrag

# Renderlo permanente via GRUB
grubby --update-kernel=ALL --args="transparent_hugepage=never"

Dopo il reboot, verificare:

cat /sys/kernel/mm/transparent_hugepage/enabled
# Output atteso: always madvise [never]

La differenza è netta: i micro-freeze random scompaiono.


🔒 Security limits #

L’utente oracle ha bisogno di limiti elevati su file descriptor aperti, processi e memoria bloccabile. I default di Linux sono pensati per utenti interattivi, non per un software che gestisce centinaia di connessioni simultanee.

cat >> /etc/security/limits.d/99-oracle.conf << 'LIMITS'
oracle   soft   nofile    65536
oracle   hard   nofile    65536
oracle   soft   nproc     16384
oracle   hard   nproc     16384
oracle   soft   stack     10240
oracle   hard   stack     32768
oracle   soft   memlock   unlimited
oracle   hard   memlock   unlimited
LIMITS
LimiteDefaultRaccomandatoPerché
nofile102465536Oracle apre un file descriptor per ogni datafile, redo log, archive log
nproc409616384Ogni processo Oracle è un processo OS separato
memlock65536 KBunlimitedNecessario per il lock della SGA in Huge Pages
stack8192 KB10240-32768 KBPL/SQL ricorsivo profondo può esaurire lo stack

Il memlock unlimited è fondamentale: senza di esso, Oracle non può bloccare la SGA nelle Huge Pages, rendendo inutile la configurazione fatta prima.


⚡ Swappiness #

Il valore di default di vm.swappiness è 60. Significa che Linux inizia a swappare quando la pressione sulla memoria è ancora bassa. Per un server database dedicato, questo è inaccettabile: vuoi che la SGA resti in RAM, sempre.

echo "vm.swappiness = 1" >> /etc/sysctl.d/99-oracle.conf
sysctl -p /etc/sysctl.d/99-oracle.conf

Non zero — uno. Il valore zero disabilita completamente lo swap, il che può causare OOM killer in situazioni di pressione estrema. Il valore uno dice al kernel: “Swappa solo se non c’è davvero più alternativa.”


📊 Prima e dopo #

Dopo aver applicato tutte le configurazioni e riavviato l’istanza Oracle, ho rifatto le misurazioni.

MetricaPrimaDopoVariazione
SGA in Huge PagesNo
Library cache hit ratio92,3%99,7%+7,4%
Buffer cache hit ratio94,1%99,2%+5,1%
Average wait time (db file sequential read)8,2 ms1,4 ms-83%
Micro-freeze random (>1s)5-8 al giorno0-100%
Tempo medio batch mattutino47 min22 min-53%
CPU utilization media78%41%-47%
Swap utilizzato3,2 GB0 MB-100%

I numeri parlano da soli. La stessa macchina, lo stesso database, lo stesso carico di lavoro. L’unica differenza: il sistema operativo è stato configurato per fare il suo lavoro.


📋 Checklist finale #

Per chi vuole un riepilogo operativo, ecco la checklist completa:

# /etc/sysctl.d/99-oracle.conf
vm.nr_hugepages = 33280
vm.swappiness = 1
kernel.shmmax = 68719476736
kernel.shmall = 16777216
kernel.shmmni = 4096
kernel.sem = 250 32000 100 256
# /etc/security/limits.d/99-oracle.conf
oracle   soft   nofile    65536
oracle   hard   nofile    65536
oracle   soft   nproc     16384
oracle   hard   nproc     16384
oracle   soft   stack     10240
oracle   hard   stack     32768
oracle   soft   memlock   unlimited
oracle   hard   memlock   unlimited
# GRUB
grubby --update-kernel=ALL --args="transparent_hugepage=never elevator=deadline"

Dieci minuti di configurazione. Nessun costo hardware. Nessuna licenza aggiuntiva.

Ma nessuno lo fa, perché il wizard non lo chiede, la documentazione è sepolta in una nota MOS, e il sistema “funziona anche senza.” Funziona. Male. E la colpa ricade sempre su Oracle, mai sul fatto che nessuno ha preparato il terreno.

Un database è buono quanto il sistema operativo su cui gira. E un sistema operativo lasciato ai default è un sistema operativo che lavora contro di te.


Glossario #

Huge Pages — Pagine di memoria da 2 MB (invece dei 4 KB standard) che riducono drasticamente la pressione sulla MMU e sul TLB, migliorando le performance di Oracle su Linux.

THP — Transparent Huge Pages — funzione del kernel Linux che promuove automaticamente le pagine normali a pagine grandi, ma che causa latenze imprevedibili e deve essere disabilitata per Oracle.

SGA — System Global Area — area di memoria condivisa di Oracle Database che contiene buffer cache, shared pool, redo log buffer e altre strutture critiche per le performance.

I/O Scheduler — Componente del kernel Linux che decide l’ordine in cui le richieste di I/O vengono inviate al disco, con impatto diretto sulle performance del database.

Swappiness — Parametro kernel Linux (vm.swappiness) che controlla la propensione del sistema a spostare pagine di memoria nello swap, critico per i server database.