Oracle Multithreaded (12c) : Quésaco ?

Avez vous regardé ce qu’apporte  la nouvelle fonctionnalité appelée « Multithreaded » par Oracle ?
J’ai pris la peine de faire quelques essais qui se sont révélés fructueux, je partage ici ma modeste expérience avec vous.

Pourquoi utiliser Oracle Multithreaded ?

Oracle Multithreaded est un mode de gestion des processus Oracle par l’utilisation des « threads », mode bien connu des DBA qui utilisent WIndows mais nouveau sous Unix.
Pour quel usage ? il y a encore de nos jours des applications (ex : les applications PHP) qui n’utilisent pas de « Pools » de connections et donc génèrent une session par utilisateur connecté (et donc un process unix).
Ce genre d’application peut conduire une base de données à exploiter des centaines (ou milliers) de process unix et donc générer de couteux « context switches » entrainant une surconsommation de CPU (impact performance & licensing).
Il existe plusieurs solutions à ce problème (par ordre d’ancienneté) :

Solution

Description Avantages inconvénient
Shared Servers Mise en oeuvre de « dispatchers » qui font du pooling de sessions dans des processus spécifiques. Existe depuis la 8i.Fonctionne très bien pour les sessions « longues » Peu efficient avec les sessions de courte durée.
Database Resident Connection Pooling (DRCP) DRCP fait du « pooling » de sessions au niveau Database, ces sessions sont partagées par les applicatifs (4). Existe depuis la 11g. Possibilité de partager un même pool entre plusieurs applications (1).Efficace. Pas de « pooling » des processus d’arrière plan (plus de 30 par instance en 12c).Non supporté par tous les « drivers » de connexion (2).Configuration coté client à réaliser.
Multithreaded configuration Configuration de la base de données pour qu’elle regroupe les sessions dans des processus : utilisation des threads (3). Pas de changement coté client ou applicatif.Pooling de l’ensemble des processus (y compris arrière plan) Disponible à partir de la 12c.
(1) Si vous avez 10 serveurs d'application qui gèrent chacun 20 connexions dans un pool mais uniquement 25 sessions actives à un instant "t" au niveau Database, il est plus efficace de gérer un pool de 30 connexions partagées par l'ensemble des applications.
(2) Oracle Database doit être en version 11g ou supérieure. Le driver PHP OCI doit être en version OCI8 1.3 ou supérieure.
(3) Les plateformes Windows ont toujours fonctionné en mode "Multithreaded", cette nouvelle fonctionnalité 12c ne concerne donc que les plateformes Unix/Linux.
(4)    Extrait de http://www.oracle.com/technetwork/articles/oracledrcp11g-1-133381.pdf

 

Configuration

Simple : il n’y a qu’un paramètre à changer au niveau instance + 1 ligne à ajouter au niveau du listener.
Mais avant cela, regardons le nombre de  processus arrière plan utilisés par une base Oracle 12c par défaut (OEL) :

[oracle@oel6-db12C-tbo ~]$ ps -ef|grep MYCDB
oracle    2736     1  0 11:18 ?        00:00:00 ora_pmon_MYCDB
oracle    2738     1  0 11:18 ?        00:00:00 ora_psp0_MYCDB
oracle    2740     1 27 11:18 ?        00:00:40 ora_vktm_MYCDB
oracle    2744     1  0 11:18 ?        00:00:00 ora_gen0_MYCDB
oracle    2746     1  0 11:18 ?        00:00:00 ora_mman_MYCDB
oracle    2750     1  0 11:18 ?        00:00:00 ora_diag_MYCDB
oracle    2752     1  0 11:18 ?        00:00:00 ora_dbrm_MYCDB
oracle    2754     1  0 11:18 ?        00:00:00 ora_dia0_MYCDB
oracle    2756     1  0 11:18 ?        00:00:00 ora_dbw0_MYCDB
oracle    2758     1  0 11:18 ?        00:00:00 ora_lgwr_MYCDB
oracle    2760     1  0 11:18 ?        00:00:00 ora_ckpt_MYCDB
oracle    2762     1  0 11:18 ?        00:00:00 ora_smon_MYCDB
oracle    2764     1  0 11:18 ?        00:00:00 ora_reco_MYCDB
oracle    2766     1  0 11:18 ?        00:00:00 ora_lreg_MYCDB
oracle    2768     1  1 11:18 ?        00:00:02 ora_mmon_MYCDB
oracle    2770     1  0 11:18 ?        00:00:00 ora_mmnl_MYCDB
oracle    2772     1  0 11:18 ?        00:00:00 ora_d000_MYCDB
oracle    2774     1  0 11:18 ?        00:00:00 ora_s000_MYCDB
oracle    2776     1  0 11:18 ?        00:00:00 ora_n000_MYCDB
oracle    2788     1  0 11:18 ?        00:00:00 ora_tmon_MYCDB
oracle    2790     1  0 11:18 ?        00:00:00 ora_tt00_MYCDB
oracle    2792     1  0 11:18 ?        00:00:00 ora_smco_MYCDB
oracle    2794     1  0 11:18 ?        00:00:00 ora_aqpc_MYCDB
oracle    2798     1  3 11:18 ?        00:00:03 ora_p000_MYCDB
oracle    2800     1  4 11:18 ?        00:00:06 ora_p001_MYCDB
oracle    2802     1  0 11:18 ?        00:00:00 ora_p002_MYCDB
oracle    2804     1  0 11:18 ?        00:00:00 ora_w000_MYCDB
oracle    2806     1  0 11:18 ?        00:00:00 ora_p003_MYCDB
oracle    2808     1  1 11:18 ?        00:00:01 ora_cjq0_MYCDB
oracle    2830     1  0 11:18 ?        00:00:00 ora_qm02_MYCDB
oracle    2834     1  0 11:18 ?        00:00:00 ora_q002_MYCDB
oracle    2836     1  0 11:18 ?        00:00:00 ora_q003_MYCDB
oracle    2848     1  0 11:18 ?        00:00:00 ora_p004_MYCDB
oracle    2850     1  0 11:18 ?        00:00:00 ora_p005_MYCDB
oracle    2852     1  0 11:18 ?        00:00:00 ora_p006_MYCDB
oracle    2854     1  0 11:18 ?        00:00:00 ora_p007_MYCDB

33 processus sans aucune session Oracle connectée.
Passons en mode « multithreaded »:
Il faut modifier le paramètre “thread_execution” comme suit:

SQL> show parameter threaded_execution
NAME                                                         TYPE  VALUE
------------------------------------ ----------- ------------------------------
threaded_execution                                boolean            FALSE
SQL> alter system set threaded_execution=TRUE scope=spfile;

Redémarrer l’instance.
Ensuite nous configurons le listener (c’est lui qui est responsable de la création des processus coté serveur lors de l’initialisation d’une session Oracle) en ajoutant la dernière ligne ci-dessous :

# listener.ora Network Configuration File: /u01/app/oracle/product/12.1.0/dbhome_1/network/admin/listener.ora
# Generated by Oracle configuration tools.
LISTENER =
  (DESCRIPTION_LIST =
    (DESCRIPTION =
      (ADDRESS = (PROTOCOL = IPC)(KEY = EXTPROC1521))
      (ADDRESS = (PROTOCOL = TCP)(HOST = oel6-db12C-tbo)(PORT = 1521))
    )
  )
DEDICATED_THROUGH_BROKER_LISTENER=ON

Redémarrer le listener.
C’est tout.
Si on regarde les processus d’arrière plan, on constate qu’après la configuration en mode « multithreaded » il ne reste plus que 6 processus (au lieu de 33) :

[oracle@oel6-db12C-tbo admin]$ ps -ef|grep MYCDB
oracle    5225     1  0 11:45 ?        00:00:00 ora_pmon_MYCDB
oracle    5227     1  0 11:45 ?        00:00:00 ora_psp0_MYCDB
oracle    5229     1 30 11:45 ?        00:00:10 ora_vktm_MYCDB
oracle    5233     1  2 11:45 ?        00:00:00 ora_u004_MYCDB
oracle    5238     1 53 11:45 ?        00:00:18 ora_u005_MYCDB
oracle    5245     1  0 11:45 ?        00:00:00 ora_dbw0_MYCDB

 

Effets de bord notables

On ne peut plus utiliser l’authentification OS:

[oracle@oel6-db12C-tbo admin]$ sqlplus / as sysdba
SQL*Plus: Release 12.1.0.1.0 Production on Fri Sep 13 11:48:05 2013
Copyright (c) 1982, 2013, Oracle.  All rights reserved.
ERROR:
ORA-01017: invalid username/password; logon denied
 [oracle@oel6-db12C-tbo admin]$
[oracle@oel6-db12C-tbo admin]$ sqlplus sys as sysdba
SQL*Plus: Release 12.1.0.1.0 Production on Fri Sep 13 11:48:13 2013
Copyright (c) 1982, 2013, Oracle.  All rights reserved.
Enter password:
Connected to:
Oracle Database 12c Enterprise Edition Release 12.1.0.1.0 - 64bit Production
With the Partitioning, OLAP, Advanced Analytics and Real Application Testing options
SQL>

Ce n’est pas un bug (source : Oracle) mais le comportement attendu.
On ne doit plus terminer des sessions via les commandes Unix de type « kill » (les sessions étant groupées dans les processus il faut utiliser les commandes Oracle correspondantes) :

SQL> select s.username,sid as session_id, spid as process_id, stid as thread_id,
pname as process_name from v$process p, v$session s  WHERE  s.paddr = p.addr order by process_id,
thread_id; (results are filtered on spid 10959);
username     sid process_id   thread_id     process_name
------------ --- ---------------- ----------------- ----
            1018 10959            10959             SCMN
             765 10959            10961             DIAG
               2 10959            10963             DIA0
             257 10959            10971             RECO
             767 10959            10973             MMON
            1020 10959            10974             MMNL
             514 10959            10984             TMON
             768 10959            10985             TT00
            1021 10959            10986             SMCO
            1275 10959            10987             FBDA
               4 10959            10988             AQPC
             258 10959            10989             W000
             515 10959            11015             CJQ0
             771 10959            11030             QM02
            1277 10959            11032             Q002
               6 10959            11033             Q003
SYS          510 10959            11093
            1029 10959            11129             W001
             268 10959            11182             W002
            1023 10959            11193             W003
SOE          521 10959            11251
SOE          775 10959            11252
SOE         1279 10959            11253
SOE            9 10959            11254
SOE          262 10959            11255
SOE          516 10959            11256
SOE          770 10959            11257
SOE         1028 10959            11258
SOE         1283 10959            11259
SOE            8 10959            11260

Quel impact sur les performances?

Pour réaliser mes tests j’ai utilisé l’outil Swingbench (qui ne supporte pas DRCP par ailleurs).
J’ai réalisé plusieurs « Run », en faisant varier le nombre de sessions en entrée de l’application :

process

Le nombre de processus reste faible en « multithreaded », 17 processus système pour 400 sessions utilisateur et 33 processus d’arrière plan Oracle.
En mode « normal », il n’y a pas de données au dela de 300 sessions, le système sous-jacent n’ayant pas permis de réaliser le test (saturation système générant des timeouts applicatifs) -> on peut donc en déduire que dans notre cas, à configuration identique, le mode « multithreaded » rend notre plateforme 25% plus scalable (le système a saturé au dela de 400 sessions).

 transactions per second

 On note que la base de données est plus performante en « multithreaded » mais aussi que cette performance est beaucoup plus constante lors de la montée en charge.

Conclusion

Ce mode de fonctionnement ne sera pas utile à tout le monde, les serveurs d’applications réalisent en général un « pooling » efficace.
Pour ceux qui par contre sont contraints à faire du client-serveur, ce mode de fonctionnement permet d’améliorer significativement la scalabilité, et ce gratuitement et sans s’engager dans un projet d’infrastructure.