Activation des threads

La mise en place du mode thread_execution est déjà couverte par de nombreux blogs. Ludovico, Franck ont déjà discuté de la mise en place et des limites ; je vous donne quand même les commandes que j'ai passé pour le mettre en place :

Configuration classique (pré-11g)

Dans le mode standard, une nouvelle connexion s'effectue ainsi côté serveur :

  • La connexion SQL*Net arrive sur le listener (IP + Port)
  • Le listener valide que la connexion demandée est possible : le service ou SID est enregistré
  • Fork du process listener pour dédier un process OS à la nouvelle connexion.


A l'issue de ces étapes, la connexion a un processus qui lui est dédiée sur le serveur avec notamment son espace mémoire contenant la PGA.
Cette solution est pratique si vous avez une faible consolidation des instances sur vos serveurs mais dès qu'on met plusieurs instances sur le même serveur, le nombre de processus est très important. De plus, avec la version 12c, le nombre de process background par instance est toujours plus important. Un exemple avec mon instance ORCL2 de test qui ne subie aucune charge :

ps --User oracle -f | awk '{ if ( $3 == 1 && $8 ~ /ORCL2/ ) print }' | wc -l
65

Activation de l'architecture Threaded

Cela se fait de façon très simple et intuitive :
SQL> alter system set threaded_execution=TRUE scope=spfile;

System altered.
et on relance l'instance :
SQL> startup force;
ERROR:
ORA-01017: invalid username/password; logon denied

ORA-01017: invalid username/password; logon denied
... ça ne se passe pas correctement :) !
Avec l'exécution en mode thread, les connexions INTERNAL (/ as sysdba) ne peuvent plus être validées par l'instance. Il est nécessaire d'utiliser une connexion User - Password !
Nouvelle tentative en utilisant la connexion user/password:
SQL> connect sys/syspassword as sysdba
Connected.

SQL> startup force;
ORACLE instance started.
Total System Global Area 2499805184 bytes
Fixed Size 2927480 bytes
Variable Size 671089800 bytes
Database Buffers 1811939328 bytes
Redo Buffers 13848576 bytes
Database mounted.
Database opened.

SQL> select INSTANCE_NAME,STATUS from v$instance;
INSTANCE_NAME STATUS

ORCL2 OPEN
Voilà qui est mieux.

Les effets sur le nombre de process OS:

Est-ce que ce paramétrage sert à quelque chose ?
ps --User oracle -f | awk '{ if ( $3 == 1 && $8 ~ /ORCL2/ ) print }'
oracle 30423 1 0 16:59 ? 00:00:00 ora_pmon_ORCL2
oracle 30425 1 0 16:59 ? 00:00:00 ora_psp0_ORCL2
oracle 30427 1 1 16:59 ? 00:00:01 ora_vktm_ORCL2
oracle 30431 1 1 16:59 ? 00:00:01 ora_u004_ORCL2
oracle 30437 1 7 16:59 ? 00:00:08 ora_u005_ORCL2
oracle 30444 1 0 16:59 ? 00:00:00 ora_dbw0_ORCL2
Clairement dans mon cas ! L'instance sans activité est passée de 65 processus à 6. Vous pouvez-voir les 2 process u000 qui sont les nouveaux processus contenant les threads pour l'instance (u pour User ?).
Vous pouvez lister les threads dans les process (sous RedHat7) via la commande ps huH:
Démo avec mon processus u004 précédent:
oracle 30431 1 1 16:59 ? 00:00:01 ora_u004_ORCL2
qui donne:
ps huH p 30431 | wc -l
11

et pour le u005:
oracle 30437 1 7 16:59 ? 00:00:08 ora_u005_ORCL2
ps huH p 30437 | wc -l
44

Il y a donc 11 threads sur le u004 et 44 sur le u005 ; on ajoute les 4 processus (pmon, psp, vktm et dbw) nous arrivons au total de 59 threads.

Sessions distantes en mode thread

Ne commencez pas à consolider vos instances tout de suite. Nous n'avons pas modifié le listener ; comme vous avez bien suivi : une nouvelle connexion = un nouveau processus puisque le listener fait un fork OS.
On n' a pas touché au listener alors, il n'y a aucune raison que cela change. La preuve avec le lancement de 100 connexions SQL*Net sur ma base :
ps --User oracle -f | awk '{ if ( $3 == 1 && $8 ~ /ORCL2/ ) print }' | wc -l
106
Exactement les 6 processus background + les 100 processus pour les connexions clientes.
Pour que le listener utilise un mode thread, nous ajoutons le paramètre suivant (dans listener.ora) :
DEDICATED_THROUGH_BROKER_Listener_Name=ON
puis rechargement :
lsnrctl reload listener

LSNRCTL for Linux: Version 12.1.0.2.0 - Production on 04-MAR-2016 17:20:13
Copyright (c) 1991, 2014, Oracle. All rights reserved.

Connecting to (DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=vm1.lab.local)(PORT=1521)))
The command completed successfully
Cette fois, nous n'avons qu'un processus "multithread process" (u000). Oracle détermine le nombre de processus de ce type a créer :
$ ps --User oracle -f | awk '{ if ( $3 == 1 && $8 ~ /ORCL2/ ) print }'
oracle 30423 1 0 16:59 ? 00:00:00 ora_pmon_ORCL2
oracle 30425 1 0 16:59 ? 00:00:00 ora_psp0_ORCL2
oracle 30427 1 2 16:59 ? 00:00:27 ora_vktm_ORCL2
oracle 30431 1 1 16:59 ? 00:00:26 ora_u004_ORCL2
oracle 30437 1 14 16:59 ? 00:03:06 ora_u005_ORCL2
oracle 30444 1 2 16:59 ? 00:00:27 ora_dbw0_ORCL2
oracle 31802 1 99 17:20 ? 00:02:04 ora_u000_ORCL2
et les multithreads process ont bien plus de threads que précédemment :
$ ps huH p 31802 | wc -l
46
$ ps huH p 30437 | wc -l
97
$ ps huH p 30431 | wc -l
11

Nous venons de modifier le listener qui peut être partagé entre plusieurs instances. Quels sont les effets pour la seconde instance ?
Aucun, ma seconde instance ORCL3 écoute également sur le même listener et mes 100 sessions clientes impliquent chacune un process OS :
ps --User oracle -f | awk '{ if ( $3 == 1 && $8 ~ /ORCL3/ ) print }' | wc -l
176

Démarrage des instances

Comme nous avons vu, dès que l'instance utilise l'architecture threads, les connexions INTERNAL ne sont plus possibles. Cela a des impacts sur les scripts de démarrage de l'instance.
Pour ma part, j'utilise toujours le script dbora proposé par Oracle. A ce propos. j'ai récemment découvert l'API https://apex.oracle.com/pls/apex/f?p=22258:1:::::: qui permet simplement d'avoir le script supporté par Oracle.
Sauf que ce script exécute le dbstart (présent sous ORACLE_HOME/bin) qui fait une connexion internal pour démarrer la base.
Le script dbora Oracle ne supporte pas le mode multithreads ; il faut passer par une autre méthode !

Oracle Grid Infrastructure

Si vous utilisez l'architecture grid infrastructure, le problème ne se pose pas et maintenant, ça serait la solution que je vous conseille car la plus élégante même pour un serveur Standalone.
Il vous faut donc commencer par installer Oracle Grid Infrastructure (disponible sans sur-coût si installé sur une machine ayant une licence base de donnée) puis une fois le Grid installé en architecture non-cluster (aussi nommée Oracle Restart), vous pouvez vous lancer sur la création de la DB.
Lors de l'exécution de dbca, vous aurez une option pour enregistrer la base sur le Grid ; si vous continuez de cette façon, vous aurez un beau script dbora enregistré dans les script d'initialisation du système.
RedHat7 oblige, vous utiliserez les commandes systemctl pour voir l'état des services:
systemctl status dbora
● dbora.service - SYSV: Oracle auto-start/stop script
Loaded: loaded (/etc/rc.d/init.d/dbora)
Active: active (exited) since Fri 2016-03-04 18:37:53 CET; 6min ago
Docs: man:systemd-sysv-generator(8)
Process: 4445 ExecStop=/etc/rc.d/init.d/dbora stop (code=exited, status=0/SUCCESS)
Process: 4723 ExecStart=/etc/rc.d/init.d/dbora start (code=exited, status=0/SUCCESS)

Mar 04 18:37:53 oel7ocp.lab.local systemd1: Starting SYSV: Oracle auto-start/stop script...
Mar 04 18:37:53 oel7ocp.lab.local su4726: (to oracle) root on none
Mar 04 18:37:53 oel7ocp.lab.local dbora4723: Starting Oracle DB:stty: standard input: Inappropriate ioctl for device
Mar 04 18:37:53 oel7ocp.lab.local dbora4723: OK
Mar 04 18:37:53 oel7ocp.lab.local systemd1: Started SYSV: Oracle auto-start/stop script.

et la preuve que l'instance démarre correctement :
sqlplus sys/syspassword as sysdba
SQL*Plus: Release 12.1.0.2.0 Production on Fri Mar 4 18:45:03 2016
Copyright (c) 1982, 2014, Oracle. All rights reserved.

Connected to:
Oracle Database 12c Enterprise Edition Release 12.1.0.2.0 - 64bit Production
With the Partitioning, OLAP, Advanced Analytics and Real Application Testing options

SQL> select INSTANCE_NAME,STATUS from v$instance;
INSTANCE_NAME STATUS
ORCL1 OPEN

Conclusion

Pour terminer cette analyse, nous avons vu que l'exécution en mode thread plutôt que processus est tout à fait possible sous les OS unix.
A voir votre besoin d'activer les threads aussi sur les sessions utilisateurs. Pour ma part, je ne vois pas pourquoi l'exécution des sessions backgrounds serait meilleure en mode thread et l'inverse pour les utilisateurs. A contrario, passer les sessions utilisateurs en architecture threads améliorera les performances si votre listener subi de très nombreuses connexions / déconnexions (diminution de la charge OS pour les allocations/libération mémoires ; pour le suivi des processus).
Alors que jusqu'à présent, je n'avais aucun soucis à me passer du Grid Infrastructure, cet exemple nous montre qu'il va devenir de plus en plus utile et qu'il devient la meilleure méthode pour assurer les démarrages des bases.