0

Oracle : la gestion des “hugepages” depuis la version 19c

twitterlinkedinmail

 

Hello,

si comme bon nombre de DBAs Oracle, vous avez installé et configuré une instance de bases de données, que ce soit sur un système Linux classique ou une machine Exadata, vous avez surement été amené à mettre en place ce que l’on appelle des “HugePages”.

Qu’est-ce donc ?

Les HugePages sont des pages de 2Mo (par défaut), prises en charge par le kernel linux, que l’administrateur système et/ou bases de données peut utiliser pour les besoins d’une application. Il est tout à fait possible également, pour des machines Exadata par exemple, de définir des tailles de pages au delà de 2Mo. Une taille de page de 1Go peut être choisie pour une base manipulant de gros volumes de données et utilisant des fonctionnalités HCC (Hybrid Columnar Compression).

Par défaut, une page sur un système Linux a une taille de 4Ko. Or, lorsqu’un SGBDR traite un volume de données conséquent, il est toujours bénéfique de limiter les aller-retour entre les différentes pages de la mémoire virtuelle et la mémoire physique supportée par le serveur via la gestion de la table de pages (la TLB) et la MMU (Memory Manager Unit).

L’idée est de positionner des pages plus grandes afin de stocker une quantité de données plus importante, et surtout de les “fixer” en mémoire afin d’éviter tout phénomène de swapping. Ceci réduit également  la charge de TLB en réduisant la fragmentation mémoire allouée pour les processus.

Rappelons que dans le meilleur des mondes possibles, un serveur de bases de données ne doit pas ou peu swapper ! Et ce, que ce soit sous un système linux ou bien Windows.

Attention, le mécanisme de prise en charge des “HugePages”, y compris en 19c est toujours incompatible avec la gestion AMM Oracle (Automatic Memory Management). Définissez une SGA_TARGET et une PGA_AGGREGATE_TARGET et oubliez le MEMORY_TARGET.

 

La gestion des HugePages avant Oracle 19c

 

Avant la version 19c, et ce depuis la version 11.2.0.3, Oracle disposait déjà d’un paramètre appelé USE_LARGE_PAGES pour la prise en charge des HugePages au sein d’une instance Oracle.

Ce paramètre comportait 3 valeurs possibles :

  • TRUE : Oracle supporte la prise en charge des HugePages si celles ci sont définies. Attention, si le nombre de HugePages est trop faible, une partie de la SGA sera intégrée dans des pages conventionnelles (taille de 4Ko). Dans tous les cas, l’instance pourra démarrer.
  • FALSE : Oracle n’utilisera jamais de HugePages sur ce serveur. Seules les pages de 4Ko seront utilisées.
  • ONLY : Oracle n’utilisera que des HugePages pour la SGA de cette instance. Attention, si les paramètres systèmes sont mal définis, ou bien si la valeur SGA_TARGET est trop haute vis à vis des paramètres kernel déclarés, l’instance peut ne pas démarrer.
    Avec ce paramètre, dans les versions antérieures à la 19c, des prérequis systèmes devaient être mis en place.

 

la gestion des HugePages depuis Oracle 19c

 

Avec l’arrivée de la version 19c, Oracle a validé 2 nouvelles valeurs pour son paramètre USE_LARGE_PAGES.

  • AUTO : Oracle va calculer son besoin en terme de HugePages lors du démarrage de l’instance, le processus en informe le kernel, qui lui accorde une certaine quantité de HugePages en fonction de ses ressources RAM disponibles.
    Dans ce cas la, si le kernel dispose d’assez de mémoire (hard limit) pour configurer des HugePages, Oracle démarre avec 100% de sa SGA_TARGET avec des pages de 2Mo (soft limit). Si la place n’est pas suffisante, des pages conventionnelles de 4Ko pourront être utilisées.
  • AUTO_ONY : Oracle calcule son besoin en terme de HugePages au moment du démarrage. Si le kernel dispose d’assez d’espace mémoire pour créer ces pages de 2Mo, l’instance démarre. Si le nombre de HugePages est insuffisant, ou bien si la limite défini dans les “soft/hard limit” est mal configurée, l’instance ne démarre pas.
    A noter que cette valeur est celle définie par défaut pour les instances portées par les machines Exadata.

 

Fonctionnement

 

Voici un test-case permettant de voir comment se comporte le système linux, et notre base de données vis à vis de la configuration de ces paramètres.

Pour notre exemple, nous disposons d’un système Linux Red Hat 8.3 et d’une instance Oracle version 19.10.

[root@ip-172-44-2-107 ~]# cat /etc/redhat-release
Red Hat Enterprise Linux release 8.3 (Ootpa)

Celui ci dispose de 2 vCPU et 4 Go de RAM

[root@ip-172-44-2-107 ~]# cat /proc/meminfo | grep -i MemTotal
MemTotal: 3823056 kB

[root@ip-172-44-2-107 ~]# cat /proc/cpuinfo | grep -i core
core id : 0
cpu cores : 2
core id : 1
cpu cores : 2

 

Prérequis

Afin de pouvoir bénéficier de la prise en charge des HugesPages pour ce serveur, il faudra définir des “limits” pour le compte Oracle de notre serveur.
Nous pourrons partir du principe que, le compte Oracle pourra, au plus, bloquer en mémoire jusqu’à 1,5Go.
A définir par le compte “root” dans le fichiers “limits.conf”.

 

 # vi /etc/security/limits.conf
....
domain          type            item        value
oracle          soft         memlock      1536000
oracle          hard         memlock      1536000

 

Nous nous assurons que ce serveur ne comporte aucune configuration de HugePages éventuelle.

 
[root]# sysctl -a | grep -i hugepages
vm.nr_hugepages = 0
vm.nr_hugepages_mempolicy = 0
vm.nr_overcommit_hugepages = 0

[root]# cat /proc/meminfo | grep -i Huge
AnonHugePages: 0 kB
ShmemHugePages: 0 kB
HugePages_Total: 0
HugePages_Free: 0
HugePages_Rsvd: 0
HugePages_Surp: 0
Hugepagesize: 2048 kB
Hugetlb: 0 kB

 

Les valeurs “HugePages_Total” et “vm.nr_hugepages” sont bien nulles.

Mis à part la “limit” définie sur la mémoire à figer pour le compte Oracle, nous n’avons pas de trace de configuration HugePages sur ce serveur.

 

[oracle]$ ulimit -Sl
1536000

 

 

 

Validation du paramètre USE_LARGE_PAGES

Cas du mode AUTO

Voici les valeurs que nous avons défini sur l’init.ora de notre instance. Cette dernière se nomme CAPDATADB.

[oracle@ dbs]$ cat initCAPDATADB.ora
...
*.sga_target=1200M
*.use_large_pages='AUTO'

 

 

Nous partons sur une instance comportant 1,2Go de SGA. Le mode AUTO est choisi afin de laisser à Oracle la possibilité de monter des HugesPages.

On démarre l’instance sans monter la base.

 

[oracle@ dbs]$ sqlplus / as sysdba

SQL> startup nomount
ORACLE instance started.

Total System Global Area 1258290744 bytes
Fixed Size 8896056 bytes
Variable Size 436207616 bytes
Database Buffers 805306368 bytes
Redo Buffers 7880704 bytes

 

 

Dans l’alert.log de la base, nous voyons que l’instance Oracle a réussi à provisionner des pages de 2Mo au moment du démarrage.

 

****************************************************
Sys-V shared memory will be used for creating SGA
****************************************************
2022-07-27T15:01:09.749738+00:00
DISM started, OS id=1692
2022-07-27T15:01:09.784169+00:00
**********************************************************************
2022-07-27T15:01:09.784260+00:00
Dump of system resources acquired for SHARED GLOBAL AREA (SGA)

2022-07-27T15:01:09.784382+00:00
Per process system memlock (soft) limit = 1500M
2022-07-27T15:01:09.784459+00:00
Expected per process system memlock (soft) limit to lock
instance MAX SHARED GLOBAL AREA (SGA) into memory: 1202M
2022-07-27T15:01:09.784626+00:00
Available system pagesizes:
4K, 2048K
2022-07-27T15:01:09.784807+00:00
Supported system pagesize(s):
2022-07-27T15:01:09.784893+00:00
PAGESIZE AVAILABLE_PAGES EXPECTED_PAGES ALLOCATED_PAGES ERROR(s)
2022-07-27T15:01:09.785003+00:00
4K Configured          4              4                 NONE
2022-07-27T15:01:09.785147+00:00
2048K                601            601             601 NONE
2022-07-27T15:01:09.785230+00:00
**********************************************************************

Oracle nous indique qu’il a réussi à monter 601 pages de 2Mo afin de les utiliser pour la SGA de notre instance.

S’il l’on regarde les paramètres kernel, nous voyons bien la présence de ces pages (HugePages_Total à 601)

$ cat /proc/meminfo | grep -i Huge
AnonHugePages: 0 kB
ShmemHugePages: 0 kB
HugePages_Total: 601
HugePages_Free: 11
HugePages_Rsvd: 11
HugePages_Surp: 0
Hugepagesize: 2048 kB
Hugetlb: 1230848 kB

 

 

Même le sysctl Linux a été modifié dynamiquement pour s’adapter à ces nouvelles valeurs.

[root~]# sysctl -a | grep -i Hugepages
vm.nr_hugepages = 601
vm.nr_hugepages_mempolicy = 601
vm.nr_overcommit_hugepages = 0

 

 

 

S’il l’on regarde du coté des ipc , l’outil “sysresv” fourni par Oracle nous donne toutes les informations nécessaires sur la mémoire partagée de notre instance et les limites de notre compte Oracle.

 

[oracle ~]$ $ORACLE_HOME/bin/sysresv

IPC Resources for ORACLE_SID "CAPDATADB" :
Maximum shared memory segment size (shmmax): 18446744073692774399 bytes
Total system shared memory (shmall): 18446744004990070784 bytes
Total system shared memory count (shmmni): 4096
*********************** Dumping ipcs output ********************

------ Message Queues --------
key msqid owner perms used-bytes messages

------ Shared Memory Segments --------
key shmid owner perms bytes nattch status
0x00000000 0 oracle 600 10485760 32
0x00000000 1 oracle 600 1241513984 32
0x00000000 2 oracle 600 8388608 32
0x679d3c3c 3 oracle 600 16384 32

------ Semaphore Arrays --------
key semid owner perms nsems
0x3b5f1c70 3 oracle 600 154

*********************** End of ipcs command dump **************


***************** Dumping Resource Limits(s/h) *****************
core file size UNLIMITED/UNLIMITED
data seg size UNLIMITED/UNLIMITED
scheduling priority 0 KB/0 KB
file size UNLIMITED/UNLIMITED
pending signals 14 KB/14 KB
max locked memory 1500 MB/1500 MB
max memory size UNLIMITED/UNLIMITED
open files 256 KB/256 KB
POSIX message queues 800 KB/800 KB
real-time priority 0 KB/0 KB
stack size 32 MB/UNLIMITED
cpu time UNLIMITED/UNLIMITED
max user processes 14 KB/14 KB
virtual memory UNLIMITED/UNLIMITED
file locks UNLIMITED/UNLIMITED

***************** End of Resource Limits Dump ******************

On retrouve pour le “shmid” 1  les 1,2Go provisionnés pour la SGA. Le “max locked memory” à 1,5Go pour le compte Oracle.

 

A noter également que lorsque l’on arrête l’instance, les HugesPages restent actifs.
Attention donc si vous avez plusieurs instances sur votre serveur et que le mode AUTO est défini sur celles-ci. La première instance qui démarre prend l’espace nécessaire dans les HugesPages, les suivantes utiliseront ce qu’il reste jusqu’aux limites définies dans “ulimit -l”. Il se peut donc que des pages de 4Ko soient potentiellement utilisées pour la(les) dernière(s) instance(s) démarrée(s).

[oracle~]$ sqlplus / as sysdba
SQL> shutdown immediate
ORA-01507: database not mounted

ORACLE instance shut down.

Mais les HugesPages sont toujours présents. Les 601 pages sont toujours présentes dans la configuration kernel, mais sont maintenant vues comme libres.

 

 [root@ ~]# cat /proc/meminfo | grep -i Huge
AnonHugePages: 0 kB
ShmemHugePages: 0 kB
HugePages_Total: 601
HugePages_Free: 601
HugePages_Rsvd: 0
HugePages_Surp: 0
Hugepagesize: 2048 kB
Hugetlb: 1230848 kB

Cas du mode AUTO_ONLY

avec le mode AUTO_ONLY, pas de souci pour ce server, dans la mesure ou nous avons deja 601 HugePages provisionnées et libres.

[oracle@ dbs]$ cat initCAPDATADB.ora 
... 
*.sga_target=1200M 
*.use_large_pages='AUTO_ONLY'

 

Au démarrage

 

SQL> startup nomount
ORACLE instance started.

Total System Global Area 1258290744 bytes
Fixed Size 8896056 bytes
Variable Size 436207616 bytes
Database Buffers 805306368 bytes
Redo Buffers 7880704 bytes

Nous pouvons même voir qu’Oracle s’attribue 100% de la SGA dans les pages de 2Mo.

2022-07-27T15:28:14.054639+00:00
Available system pagesizes:
4K, 2048K
2022-07-27T15:28:14.054776+00:00
Supported system pagesize(s):
2022-07-27T15:28:14.054841+00:00
PAGESIZE AVAILABLE_PAGES EXPECTED_PAGES ALLOCATED_PAGES ERROR(s)
2022-07-27T15:28:14.054970+00:00
2048K                602            602             602 NONE
2022-07-27T15:28:14.055045+00:00
Reason for not supporting certain system pagesizes:
2022-07-27T15:28:14.055111+00:00
4K - Large pagesizes only

602 pages prises par Oracle et que le kernel enregistrera après démarrage

 

[oracle@ dbs]$ cat /proc/meminfo | grep -i Huge
AnonHugePages: 0 kB
ShmemHugePages: 0 kB
HugePages_Total: 602
HugePages_Free: 11
HugePages_Rsvd: 11
HugePages_Surp: 0
Hugepagesize: 2048 kB
Hugetlb: 1232896 kB

Au niveau des ipc rien n’a changé dans l’attribution de la mémoire partagée. Nous avons toujours le découpage SGA de 1,2Go pris sur le segment numéro 5, et le reste représentant les “fixed size”, “redo buffers”.

 

[oracle@ dbs]$ ipcs -m

------ Shared Memory Segments --------
key shmid owner perms bytes nattch status
0x00000000 4 oracle 600 10485760 32
0x00000000 5 oracle 600 1241513984 32
0x00000000 6 oracle 600 8388608 32
0x679d3c3c 7 oracle 600 2097152 32

 

Au dela des limites !

Mais que se passe-t-il si l’on choisit une SGA de taille plus importante que la “soft” limite définie pour le compte Oracle. Rappelons que nous avions capé à 1,5Go les limites en terme de “memlock” pour notre user Oracle.

Cas du mode AUTO

Supposons que nous choisissons les valeurs suivantes dans l’init.ora de notre instance. 1,8Go pour notre SGA.

 

[oracle@ dbs]$ cat initCAPDATADB.ora
...
*.sga_target=1800M
*.use_large_pages='AUTO'

Au démarrage de l’instance

SQL> startup nomount
ORACLE instance started.

Total System Global Area 1895822680 bytes
Fixed Size 8897880 bytes
Variable Size 436207616 bytes
Database Buffers 1442840576 bytes
Redo Buffers 7876608 bytes

 

L’instance démarre, mais que dit l’alert.log :

 

2022-07-27T15:38:35.723099+00:00
Available system pagesizes:
4K, 2048K
2022-07-27T15:38:35.723243+00:00
Supported system pagesize(s):
2022-07-27T15:38:35.723318+00:00
PAGESIZE AVAILABLE_PAGES EXPECTED_PAGES ALLOCATED_PAGES ERROR(s)
2022-07-27T15:38:35.723395+00:00
4K            Configured              5           79752 NONE
2022-07-27T15:38:35.723516+00:00
2048K                901            905             749 NONE
2022-07-27T15:38:35.723594+00:00
RECOMMENDATION:
2022-07-27T15:38:35.723676+00:00
1. For optimal performance, configure system with expected number
of pages for every supported system pagesize prior to the next
instance restart operation.
2022-07-27T15:38:35.727289+00:00
2. Increase per process memlock (soft) limit to at least 1810MB
to lock 100% of SHARED GLOBAL AREA (SGA) pages into physical memory
2022-07-27T15:38:35.727468+00:00
**********************************************************************

Notre instance réclame 1,8Go de SGA. Le kernel n’a pu lui fournir que 749 pages de 2Mo, soit 1498Mo, alors qu’Oracle en réclame 905.

le reste de la mémoire SGA va donc se positionner dans des pages conventionnelles de 4Ko, soit 79752 pages, donc 311Mo.

S’il l’on regarde les segments de mémoire partagée, nous voyons des espaces fragmentées , avec au plus, un espace contigu de 900Mo sur le shmid 9. Nous voyons également le shmid 14 représentant les 311 Mo en pages de 4Ko.

[oracle@ dbs]$ ipcs -m

------ Shared Memory Segments --------
key shmid owner perms bytes nattch status
0x00000000 8 oracle 600 10485760 31
0x00000000 9 oracle 600 939524096 31
0x00000000 10 oracle 600 469762048 31
0x00000000 11 oracle 600 117440512 31
0x00000000 12 oracle 600 16777216 31
0x00000000 13 oracle 600 16777216 31
0x00000000 14 oracle 600 318767104 31
0x00000000 15 oracle 600 7876608 31
0x679d3c3c 16 oracle 600 20480 31

la situation n’est pas la plus optimale, surtout dans un système ou l’on charge en mémoire de grandes volumétries de données. Il est fort possible que nous fassions d’avantage d’IO dans la mesure ou nos segments de mémoire sont fragmentés.

 

Cas du mode AUTO_ONLY

mais alors, qu’en est-il du mode AUTO_ONLY si je dépasse la valeur “soft limit” des 1,5Go ?

Nous avons auparavant déjà alloué 901 pages de 2Mo au niveau du kernel. Ces pages sont présentes, même avec notre instance arrêtée.

[oracle@ dbs]$ ipcs -m -u

------ Shared Memory Status --------
segments allocated 0
pages allocated 0
pages resident 0
pages swapped 0
Swap performance: 0 attempts 0 successes
[oracle@ dbs]$ cat /proc/meminfo | grep -i Huge
AnonHugePages: 0 kB
ShmemHugePages: 0 kB
HugePages_Total: 901
HugePages_Free: 901
HugePages_Rsvd: 0
HugePages_Surp: 0
Hugepagesize: 2048 kB
Hugetlb: 1845248 kB

Mais au démarrage de notre instance avec 1,8Go de SGA configurée

[oracle@ dbs]$ cat initCAPDATADB.ora
...
*.sga_target=1800M
*.use_large_pages='AUTO_ONLY'

 

SQL> startup nomount
ORA-27125: unable to create shared memory segment
Linux-x86_64 Error: 1: Operation not permitted
Additional information: 4641
Additional information: 16777216

 

et l’alert.log est claire

 

2022-07-27T15:54:04.922034+00:00
PAGESIZE AVAILABLE_PAGES EXPECTED_PAGES ALLOCATED_PAGES ERROR(s)
2022-07-27T15:54:04.922154+00:00
2048K                901            906             749 ORA-27125
2022-07-27T15:54:04.922230+00:00
Reason for not supporting certain system pagesizes:
2022-07-27T15:54:04.922305+00:00
4K - Large pagesizes only
2022-07-27T15:54:04.922378+00:00
RECOMMENDATION:
2022-07-27T15:54:04.922448+00:00
1. Configure system with expected number of pages for every
supported system pagesize prior to the next instance restart operation.
2022-07-27T15:54:04.925893+00:00
2. Increase per process memlock (soft) limit to at least 1812MB
to lock 100% of SHARED GLOBAL AREA (SGA) pages into physical memory
2022-07-27T15:54:04.926083+00:00
**********************************************************************

 

Nous rencontrons une erreur ORA 27125, impossible d’affecter les pages demandées, l’instance ne démarre pas.
Oracle nous conseille d’augmenter le “soft limit” afin de faire tenir les 1,8Go de SGA dans des “HugePages” de 2Mo.

 

Conclusion et préconisations

Comme nous venons de voir, Oracle, depuis la version 19c, est capable de réclamer dynamiquement au kernel des pages de 2Mo, sans pour autant les avoir provisionner dans le fichier “sysctl.conf“. Il est cependant, indispensable, de fixer des soft/hard limits au user Oracle afin de pouvoir verrouiller des pages en mémoire.

Lors du reboot du server, les paramètres “vm.nr_hugepages” et “HugePages_Total” sont remis à 0 laissant le système disposer de ses pages conventionnelles de 4Ko.

Voici les configurations que je préconiserais pour un système Linux 64 bits si vous souhaitez profiter de la gestion dynamique des HugePages par Oracle.

Cas d’un serveur dédié SGBDR avec 1 instance Oracle :

  • Positionner le SHMMAX (en bytes) de 50% à 75% de la RAM serveur. Sur un système Exadata vous pouvez monter jusqu’à 80% de la RAM pour 1 taille max de segment mémoire.
  • Positionner le SHMALL (en pages) à une taille légèrement supérieur à la valeur de SGA_TARGET.
  • les limites “memlock” hard et soft doivent être identique à SHMALL (attention en Ko).
  • Positionner USE_LARGE_PAGES à AUTO_ONLY afin de profiter des HugePages pour votre instance.
  • Bien entendu, ne pas oublier de mettre MEMORY_TARGET à 0.

 

Cas d’un serveur SGBDR avec plusieurs instances Oracle.

  • Positionner SHMMAX (en bytes) à 50% de la RAM. La taille d’un segment de mémoire ne doit pas dépasser 1/2 de la RAM. (cas d’un serveur disposant de bases de production par exemple).
  • Le SHMALL (en pages) représente la somme totale des SGA de toutes les bases, avec un marge de quelques pages.
  • Les limites “memlock” hard et soft doivent être identique à SHMALL (attention, en Ko).
  • Positionner USE_LARGE_PAGES à
    • AUTO_ONLY sur les bases dans le cas d’un serveur de production manipulant de forts volumes de données (Datawarehouse). Ceci afin de s’assurer que Oracle n’utilisera que des HugePages en mémoire et qu’il pourra les verrouiller. C’est la valeur par défaut sur une instance d’un dbnode Exadata.
    • AUTO sur un serveur comportant des bases de dev/test ou bien sur des bases ou l’on souhaite changer facilement la valeur de SGA_TARGET sans risquer d’avoir un souci de démarrage sur l’une des instances.
  • mettre MEMORY_TARGET à 0 sur toutes les instances.

Dans tous les cas, sur un serveur Linux dédié pour des instances de bases de données Oracle, il est recommandé de désactiver les Transparent Huges Pages (THP) dans la mesure ou ces pages sont dynamiquement “swappable” à la volée. Ce qui peut être très problématique, notamment dans le cadre d’un environnement RAC (éviction de nœud possible).

  • lancer la commande :
    echo never | tee /sys/kernel/mm/transparent_hugepage/enabled
  • éditer “/etc/grub.conf” et ajouter “transparent_hugepage=never

 

 

🙂

 

 

Emmanuel RAMI

Continuez votre lecture sur le blog :

twitterlinkedinmail

Emmanuel RAMI

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée.

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur comment les données de vos commentaires sont utilisées.