Cette rubrique décrit comment les API de création de requêtes eXtreme Scale et le plug-in d'indexation MapRangeIndex interagissent avec les verrous et présente les meilleures pratiques pour augmenter les accès simultanés et réduire les interblocages lors de l'utilisation de la stratégie de verrouillage pessimiste pour les mappes.
L'API de création de requêtes ObjectGrid active les requêtes SELECT sur les objets et les entités cache ObjectMap. Lorsqu'une requête est exécutée, le moteur de requête utilise un MapRangeIndex dans la mesure du possible pour trouver des clés qui correspondent aux valeurs de la clause WHERE de la requête ou pour établir des relations. Lorsqu'un index n'est pas disponible, le moteur de requête analyse chaque entrée dans une ou plusieurs mappes pour trouver les entrées appropriées. Le moteur de requête et les plug-in d'index obtiennent des verrous pour vérifier la cohérence des données en fonction de la stratégie de verrouillage, le niveau d'isolement de la transaction et l'état de la transaction.
Le plug-in eXtreme Scale HashIndex permet de trouver des clés en fonction d'un attribut unique stocké dans la valeur d'entrée du cache. L'index stocke la valeur indexée dans une structure de données distincte de la mappe du cache. L'index valide les clés avec les entrées de mappe avant d'être renvoyé à l'utilisateur afin de tenter d'obtenir un ensemble de résultats exact. Lorsque la stratégie de verrouillage pessimiste est utilisée et que l'index est utilisé avec une instance d'ObjectMap locale (contrairement à une instance d'ObjectMap client-serveur), l'index obtient des verrous pour chaque entrée correspondante. Lors de l'utilisation d'un verrouillage optimiste ou d'une instance ObjectMap distante, les verrous sont toujours immédiatement libérés.
Le type de verrou obtenu dépend de l'argument forUpdate transmis à la méthode ObjectMap.getIndex. L'argument forUpdate spécifie le type de verrou que l'index doit obtenir. Si la valeur est égale à false, un verrou (S) pouvant être partagé est obtenu et si la valeur est égale à true, un verrou (U) pouvant être mis à niveau est obtenu.
Si le type de verrou peut être partagé, le paramètre d'isolement de la transaction pour la session est appliqué et affecte la durée du verrouillage. Reportez-vous à la rubrique relative à l'isolement de transaction pour plus de détails sur l'utilisation de l'isolement de transaction pour ajouter des accès simultanés aux applications.
Le moteur de requête eXtreme Scale obtient des verrous S si nécessaire pour introspecter les entrées de cache et découvrir si elles répondent aux critères de filtrage de la requête. Lors de l'utilisation de l'isolement de transaction de lecture reproductible avec le verrouillage pessimiste, les verrous S sont uniquement conservés pour les éléments inclus dans le résultat de la requête et sont libérés pour toutes les entrées non incluses dans le résultat. Dans le cas de l'utilisation d'un niveau d'isolement de transaction inférieur ou du verrouillage optimiste, les verrous S ne sont pas conservés.
Lors de l'utilisation de la requête eXtreme Scale depuis un client, la requête s'exécute généralement sur le serveur à moins que toutes les mappes ou entités référencées dans la requête soient stockées en local sur le client (par exemple : une mappe client repliquée ou une entité de résultat de requête). Toutes les requêtes exécutées dans une transaction en lecture/écriture conservent les verrous S, tel que décrit dans la section précédente. Si la transaction n'est pas en lecture/écriture, une session n'est pas conservée sur le serveur et les verrous S sont libérés.
Les verrous partageables sont utiles lorsque l'accès simultané et la cohérence sont prioritaires. Ils garantissent l'inaltérabilité de la valeur d'une entrée pendant toute la durée de vie de la transaction. Aucune autre transaction ne peut modifier la valeur alors que d'autres verrous S sont maintenus et seule une autre transaction peut établir un objectif de mise à jour de l'entrée. Consultez la rubrique Mode de verrouillage pessimiste pour obtenir des détails sur les modes de verrouillage S, U et X.
Les verrous pouvant être mis à niveau permettent d'identifier l'objectif de mise à jour d'une entrée de cache lors de l'utilisation d'une stratégie de verrouillage pessimiste. Ils permettent la synchronisation entre les transactions qui visent à modifier une entrée de cache. Les transactions peuvent toujours visualiser l'entrée à l'aide d'un verrou S mais certaines ne peuvent pas obtenir un verrou U ou X. Dans de nombreux scénarios, il est nécessaire d'obtenir un verrou U sans acquérir un verrou S au préalable pour éviter tout interblocage. Consultez la rubrique Mode de verrouillage pessimiste pour obtenir des exemples d'interblocage.
ObjectMap orderMap = session.getMap("Order");
ObjectQuery q = session.createQuery("SELECT o FROM Order o WHERE o.orderDate=?1");
q.setParameter(1, "20080101");
q.setForUpdate(true);
session.begin();
// Exécutez la requête. Chaque commande comporte verrou U
Iterator result = q.getResultIterator();
// Pour chaque commande, mettez à jour l'état.
while(result.hasNext()) {
Order o = (Order) result.next();
o.status = "shipped";
orderMap.update(o.getId(), o);
}
// Une fois validée, la
session.commit();
Query q = em.createQuery("SELECT o FROM Order o WHERE o.orderDate=?1");
q.setParameter(1, "20080101");
q.setForUpdate(true);
emTran.begin();
// Exécutez la requête. Chaque commande comporte verrou U
Iterator result = q.getResultIterator();
// Pour chaque commande, mettez à jour l'état.
while(result.hasNext()) {
Order o = (Order) result.next();
o.status = "shipped";
}
tmTran.commit();
Lorsque l'attribut setForUpdate est activé, la transaction est automatiquement convertie en une transaction lecture-écriture et les verrous sont maintenus sur le serveur comme prévu. Si la requête ne peut pas utiliser d'index, la mappe doit être analysée, ce qui entraîne des verrous U temporaires pour les entrées de mappe qui ne répondent pas au résultat de la requête et maintient les verrous U pour les entrées qui correspondent au résultat de la requête.