Introduction
l existe un certain nombre de SGBD dont ceux qui nous intéressent dans le cadre d’Adelia sont soit sur une plate-forme micro, soit sur un serveur iSeries.
Les SGBD les plus courants sont DB2 (micro ou iSeries), Oracle, SQL Server, MySQL.
Pour réaliser des verrouillages SQL, il est nécessaire de mettre en œuvre la journalisation des tables ou fichiers de la base de données.
Il est possible de gérer cette journalisation sur l’iSeries de deux manières différentes :
- Soit de manière native dans une bibliothèque avec une journalisation des fichiers,
- Soit par l’utilisation d’une collection permettant un fonctionnement similaire aux bases de données micro par une journalisation implicite.
Le premier cas offre deux possibilités, la première est la journalisation manuelle ou à l’aide d’outillage traitant de cette journalisation et la deuxième permettant la mise en place de la journalisation implicite hors collection.
Pour mettre en place cette deuxième possibilité, vous avez plusieurs solutions depuis la V6 :
- Créer dans la bibliothèque contenant les fichiers une « data area » nommée « QDFTJRN » contenant le nom du journal,
- Utiliser la commande STRJRNLIB sur la bibliothèque,
- Que le journal QSQJRN soit présent dans la bibliothèque.
Le fonctionnement du verrouillage s’applique de manière à ce que lorsque plusieurs utilisateurs ou applications accèdent simultanément aux mêmes données, le verrouillage les empêche de modifier les données en même temps. Les verrous sont gérés en interne par le moteur de base de données et
Ils sont automatiquement acquis et libérés en fonction des actions réalisés par l'utilisateur.
Le verrouillage des enregistrements permet donc de résoudre les problèmes d’accès concurrentiels au travers du mécanisme de contrôle des transactions.
Les transactions permettent de regrouper une série de modifications de base de données dans une opération logique. Une fois les modifications effectuées, elles peuvent être validées ou annulées comme une seule unité. La transaction permet de faire passer la base de données d’un état cohérent à un état cohérent.
Il existe cependant des différences notables dans le fonctionnement de ces SGBD en ce qui concerne le verrouillage proprement dit.
En effet, dans le fonctionnement par défaut des bases micro le verrouillage est infini. En d’autre terme la demande de verrou (implicite en fonction de l’action) sur un enregistrement déjà verrouillé par une autre transaction (un autre travail) sera en attente de la fin de cette autre transaction. Le travail reste donc bloqué automatiquement jusqu’à ce que l’opération demandée puisse avoir lieu.
Pour les bases de données iSeries, le délai de verrouillage maximum est par défaut fixé à 60 secondes. Dans le cas où la transaction verrouillant l’enregistrement (de l’autre travail) n’est pas terminée et que le délai maximum de l’attente est atteint alors le SGBD signalera le blocage et rend la main.
Ce délai de verrouillage peut être modifié au travers du paramètre WAITRCD sur les fichiers physiques et logiques en fonction des besoins et des normes choisies par votre projet. La modification doit être alors appliquée sur toutes les tables et index par les commandes CHGPF et CHGLF.
Mode transactionnel
Adelia propose de gérer le mode transactionnel de deux manières différentes :
- Utiliser le contrôle de validation,
- Ignorer le contrôle de validation.
Pour cela, vous avez la possibilité de définir le mode au travers d’un attribut dans l’environnement Adelia. Il est paramétrable dans l’onglet L3G de l’environnement ou au niveau logique d’un domaine avec l’option de génération « Ignorer le contrôle de validation ».
Pour que le contrôle de validation soit gérer par l’application, il faut que la case à cocher soit décochée. Dans le cas contraire, il n’y a pas de contrainte liée au verrouillage, les instructions SQL sont validées immédiatement.
Vous avez également un paramétrage pour les programmes Adelia web dans la configuration du client. Elle permet de définir si le contrôle de validation est ignoré pour les programmes en mode conservation des connexions. C’est uniquement ce paramétrage qui fait référence pour ces programmes.
Adelia permet également de gérer le mode transactionnel par le biais de la fonction VaToolBxSetTransactionalMode à partir du moment où l’application a été générée avec contrôle de validation. Dans ce cas, le mode transactionnel peut être passé à auto-commit puis ensuite changé pour revenir au mode commit manuel.
Gestion du verrouillage
Afin de gérer les verrouillages par SQL, vous devez avoir positionné le mode transactionnel à cet effet (Ignorer le contrôle de validation à l’état non coché).
Adelia propose le mot réservé *BLOQUE permettant de savoir si une instruction d’accès à la base de données n’a pu aboutir par le fait d’un blocage d’enregistrement(s).
Dans le cas par défaut des bases de données micro, l’information d’un verrouillage d’enregistrement ne pourra survenir comme précisé dans le principe du verrouillage.
Il est probable que dans un mode interactif, vous ne souhaitiez pas que vos utilisateurs restent bloqués indéfiniment. Pour cela, vous avez la possibilité d’utiliser la fonction « VaToolBxSetTimeOut » de la DLL « VaToolBx ». Elle permet de fixer la durée maximum d’une requête SQL. Au-delà de ce délai, l’exécution de la requête est interrompue et le mot réservé « *BLOQUE » est positionné à la valeur 1 (enregistrement verrouillé).
Il faut utiliser cette fonction avec beaucoup d’attention car elle traite d’un délai sur une requête. Hors, si vous avez des requêtes qui demandent un délai important pour retourner l’information alors vous risquez d’obtenir un effet non désiré.
Ce paramétrage est également possible sur l’iSeries de manière global par la valeur système QQRYTIMLMT ou pour un travail donné par la commande CHGQRYA (cette commande nécessite d’avoir le droit *JOBCTL pour être utilisée).
Vous avez un intérêt tout particulier à mettre en œuvre la gestion des délais sur les blocages afin d’éviter les inter-blocages. Dans l’exemple suivant, les verrouillages sont exclusifs et sans gestion des délais, vous arrivez à une situation de blocage mortel.
Transaction 1 | Transaction 2 |
Verrouillage A | |
Verrouillage B | |
Verrouillage B | |
Attente | Verrouillage A |
Attente | Attente |
Pour éviter les verrous mortels, vous devez accorder à la transaction tous les verrous dont elle a besoin ou fixer un ordre sur les données et imposer aux transactions de respecter cet ordre dans leurs demandes de verrous.
Pour verrouiller un ou plusieurs enregistrements, vous avez différentes possibilités :
- Utiliser un curseur en mise à jour,
- Utiliser les ordres ADELIA/SQL de mise à jour ou de suppression.
L’intérêt du curseur en mise à jour est de bloquer un enregistrement dès sa lecture. Il est à utiliser en cas de besoin de lecture des données d’enregistrements. Les blocages interviennent alors au fur et à mesure des lectures.
La contrainte liée au curseur en mise à jour est de s’assurer qu’aucun ordre de contrôle de validation ne soit réalisé avant la fermeture du curseur et auquel cas, que les programmes de niveaux suivant, imbriqués dans le curseur, ne fassent pas non plus usage d’ordre de contrôle. Le risque en cas de non-respect de cette contrainte serait d’avoir des comportements inattendus et différents en fonction des SGBD avec des résultats non-conformes (arrêt des lectures, plus de verrouillage des enregistrements suivants, …).
Un des risques du curseur en mise à jour est également d’avoir une attente liée au verrouillage d’un enregistrement que l’on souhaite lire puis d’obtenir l’information de blocage de celui-ci. Dans ce cas, il faudra en tenir compte de manière très rigoureuse dans le processus global qui sera mis en œuvre et le traiter de manière cohérente dans l’application.
L’intérêt de l’ordre SQL de mise à jour ou suppression est de bloquer un ou plusieurs enregistrements en une seule fois sans pour autant avoir besoin de les lire auparavant. Ce type d’ordre est utilisé sur des actions classiques de modification ou suppression des données mais également lors d’un besoin particulier de blocage d’enregistrement. Dans ce dernier cas, une mise à jour « bidon » est réalisée « MAJ_SQL ENTITE COL_CLE = :VALEUR_CLE *COND(COL_CLE = :VALEUR_CLE) ».
Dans tous les cas, vous devrez prendre en compte l’information sur le blocage d’enregistrement après ces différents ordres (d’autant plus sur iSeries) et le traiter de manière cohérente à vos chaines de traitement.
Une particularité est à noter en fonction de la typologie du contrôle de validation.
- Sur la plateforme iSeries, le paramètre COMMIT de compilation des programmes SQL permet de définir certains aspects du mode de fonctionnement du verrouillage. Il en découle une incidence sur la visibilité des informations par les autres travaux (instance différente). Il est donc important de savoir ce que l’on souhaite mettre en œuvre dans un projet et le mode de fonctionnement associé.
- Vous avez cependant la possibilité d’utiliser l’ordre SQL suivant pour DB2/400 :
SET TRANSACTION ISOLATION LEVEL {NO COMMIT | READ UNCOMMITTED, READ WRITE | READ COMMITED | REPEATABLE READ | SERIALIZABLE}
- NO COMMIT => NONE
- READ UNCOMMITTED => UR,
- READ UNCOMMITTED, READ WRITE => CHG
- READ COMMITED => CS
- REPEATABLE READ => RS ou ALL
- SERIALIZABLE => RR
- Ordre confirmé depuis la version V4r4.
- Pour les autres SGBD, il est également possible de modifier la typologie de contrôle de validation par des ordres SQL spécifiques à la base de données. Ces informations sont à rechercher en fonction du SGBD à utiliser.
- Pour DB2 (micro)vous avez l’ordre SQL suivant :
- SET TRANSACTION ISOLATION LEVEL {READ UNCOMMITTED, READ WRITE | READ COMMITED | REPEATABLE READ | SERIALIZABLE}
- Attention, il existe des différences en fonction des versions.
- Pour SQLSERVER vous avez l’ordre SQL suivant :
- SET TRANSACTION ISOLATION LEVEL {READ UNCOMMITTED | READ COMMITTED | REPEATABLE READ | SNAPSHOT | SERIALIZABLE}
- Attention, certaine option ne sont pris en charge en fonction de la version.
- Pour ORACLEvous avez également l’ordre SQL suivant :
- SET TRANSACTION …
- Ordre confirmé depuis la version 6 avec quelques variantes possibles
- Pour MySqlvous avez également l’ordre SQL suivant :
- SET [ GLOBAL | SESSION ] TRANSACTION ISOLATION LEVEL {READ UNCOMMITTED | READ COMMITTED | REPEATABLE READ | SERIALIZABLE}
- Ordre confirmé depuis la version 3.23
- Pour DB2 (micro)vous avez l’ordre SQL suivant :