In diesem Abschnitt wird beschrieben, wie die Query-APIs von eXtreme Scale und das Indexierungs-Plug-in "MapRangeIndex" mit Sperren interagieren. Außerdem werden einige bewährte Verfahren vorgestellt, mit denen Sie die Anzahl der gemeinsamen Zugriffe erhöhen und die Anzahl der Deadlocks verringern können, wenn Sie die pessimistische Sperrstrategie für Maps verwenden.
Mit der ObjectGrid-Query-API können SELECT-Abfragen von ObjectMap-Cacheobjekten und -Entitäten ausgeführt werden. Bei der Ausführung einer Abfrage verwendet die Abfragesteuerkomponente, sofern möglich, einen MapRangeIndex, um Schlüssel zu suchen, die Werten in der WHERE-Klausel der Abfrage entsprechen, oder um Beziehungen zu überbrücken. Wenn kein Index verfügbar ist, scannt die Abfragesteuerkomponente jeden Eintrag in einer oder mehreren Maps, um die entsprechenden Entitäten zu finden. Sowohl die Abfragesteuerkomponente als auch die Index-Plug-ins fordern je nach Sperrstrategie, Transaktionsisolationsstufe und Transaktionsstatus Sperren an, um die Datenkonsistenz zu prüfen.
Mit dem HashIndex-Plug-in von eXtreme Scale können Schlüssel auf der Basis eines einzelnen Attributs, das im Cacheeintragswert gespeichert ist, gesucht werden. Im Index wird der indexierte Wert in einer von der Cache-Map abgesonderten Datenstruktur gespeichert. Der Index vergleicht die die Schlüssel mit den Map-Einträgen, bevor er sie an den Benutzer zurückgibt, um eine genaue Ergebnismenge zu erhalten. Wenn Sie die pessimistische Sperrstrategie verwenden und der Index für eine lokale ObjectMap-Instanz (im Gegensatz zu einer Client/Server-ObjectMap) verwendet wird, fordert der Index eine Sperre für jeden übereinstimmenden Eintrag an. Wenn Sie optimistisches Sperren oder eine ferne ObjectMap verwenden, werden die Sperren immer sofort freigegeben.
Der Typ der angeforderten Sperre richtet sich nach dem Argument "forUpdate", das an die Methode "ObjectMap.getIndex" übergeben wird. Das Argument "forUpdate" gibt den Typ der Sperre an, die der Index anfordern sollte. Wenn dieses Argument den Wert "false" hat, wird eine gemeinsame Sperre (S-Sperre) angefordert, wenn es den Wert "true" hat, wird eine aktualisierbare Sperre (U-Sperre) angefordert.
Bei einer S-Sperre wird die Einstellung der Transaktionsisolationsstufe für die Sitzung angewendet, die sich auf die Dauer der Sperre auswirkt. Im Abschnitt zu den Transaktionsisolationsstufen wird ausführlich beschreiben, wie über die Transaktionsisolationsstufen die Anzahl gemeinsamer Zugriffe auf Anwendungen erhöht werden kann.
Die Abfragesteuerkomponente von eXtreme Scale fordert bei Bedarf S-Sperren an, um die Cacheeinträge dahingehend zu überwachen, ob sie die Filterkriterien der Abfrage erfüllen. Wenn Sie die Transaktionsisolationsstufe "repeatable read" (wiederholbares Lesen) mit pessimistischem Sperren verwenden, werden die S-Sperren nur für die Elemente beibehalten, die im Abfrageergebnis enthalten sind, und für die Einträge, die nicht im Ergebnis enthalten sind, freigegeben. Wenn Sie eine niedrigere Transaktionsisolationsstufe oder optimistisches Sperren verwenden, werden die S-Sperren nicht beibehalten.
Wenn Sie die eXtreme-Scale-Abfrage über einen Client absetzen, wird die Abfrage gewöhnlich im Server ausgeführt, sofern nicht alle Maps oder Entitäten, die in der Abfrage referenziert werden, lokal im Client vorhanden sind (z. B., wenn es sich um eine im Client replizierte Map oder Abfrageergebnisentität handelt). Alle Abfragen, die in einer Transaktion mit Lese-/Schreibzugriff ausgeführt werden, halten S-Sperren so, wie es im vorherigen Abschnitt beschrieben wurde. Wenn die Transaktion keine Transaktion mit Lese-/Schreibzugriff ist, wird keine Sitzung im Server gehalten, und die S-Sperren werden freigegeben.
Gemeinsame Sperren sind hilfreich, wenn gemeinsamer Zugriff und Konsistenz wichtig sind. Sie gewährleisten, dass sich der Wert eines Eintrags während der gesamten Lebensdauer der Transaktion nicht ändert. Der Wert kann von anderen Transaktionen nicht geändert werden, während andere S-Sperren gehalten werden, und nur eine einzige andere Transaktion kann ihre Absicht zum Aktualisieren des Eintrags manifestieren. Einzelheiten zu S-, U- und X-Sperren finden Sie im Abschnitt zum pessimistischen Sperrmodus.
Aktualisierbare Sperren werden verwendet, um die Absicht zum Aktualisieren eines Cacheeintrags bekannt zu geben, wenn die pessimistische Sperrstrategie verwendet wird. Sie lassen eine Synchronisation von Transaktionen zu, die einen Cacheeintrag ändern möchten. Transaktionen können den Eintrag weiterhin über eine S-Sperre anzeigen, aber andere Transaktionen werden an der Anforderung einer U- bzw. X-Sperre gehindert. In vielen Szenarien ist die Anforderung einer U-Sperre ohne vorherige Anforderung einer S-Sperre erforderlich, um Deadlocks zu vermeiden. Beispiele für häufige Deadlocks finden Sie im Abschnitt zum pessimistischen Sperrmodus.
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();
// Abfrage ausführen. Jeder Auftrag (order) hat eine U-Sperre.
Iterator result = q.getResultIterator();
// Für jeden Auftrag (order) den Status aktualisieren.
while(result.hasNext()) {
Order o = (Order) result.next();
o.status = "shipped";
orderMap.update(o.getId(), o);
}
// Festschreibung
session.commit();
Query q = em.createQuery("SELECT o FROM Order o WHERE o.orderDate=?1");
q.setParameter(1, "20080101");
q.setForUpdate(true);
emTran.begin();
// Abfrage ausführen. Jeder Auftrag (order) hat eine U-Sperre.
Iterator result = q.getResultIterator();
// Für jeden Auftrag (order) den Status aktualisieren.
while(result.hasNext()) {
Order o = (Order) result.next();
o.status = "shipped";
}
tmTran.commit();
Wenn das Attribut setForUpdate aktiviert ist, wird die Transaktion automatisch in eine Transaktion mit Lese-/Schreibzugriff konvertiert, und die Sperren werden im Server wie erwartet gehalten. Falls die Abfrage keine Indizes verwenden kann, muss die Map gescannt werden, was dazu führt, dass temporäre U-Sperren für Map-Einträge gesetzt werden, die nicht im Abfrageergebnis enthalten sind, und U-Sperren für Einträge gehalten werden, die im Ergebnis enthalten sind.