Auf dieser Seite werden Transaktionen in Spanner erläutert. Außerdem finden Sie hier Beispielcode zum Ausführen von Transaktionen.
Einleitung
Bei einer Transaktion in Spanner handelt es sich um eine Gruppe von Lese- und Schreibvorgängen, die zu einem einzigen logischen Zeitpunkt über Spalten, Zeilen und Tabellen in einer Datenbank atomisch ausgeführt wird.
Spanner unterstützt diese Transaktionsmodi:
Lese-/Schreibtransaktionen sperren. Diese Transaktionen basieren auf einer pessimistischen Sperrung und, falls notwendig, einem zweiphasigen Commit. Beim Sperren können Lese-Schreib-Transaktionen abgebrochen werden. In diesem Fall muss die Anwendung den Vorgang wiederholen.
Schreibgeschützt. Dieser Transaktionstyp bietet garantierte Konsistenz über mehrere Lesevorgänge, unterstützt jedoch keine Schreibvorgänge. Schreibgeschützte Transaktionen werden standardmäßig zu einem vom System ausgewählten Zeitstempel ausgeführt, der für externe Konsistenz sorgt. Sie können aber auch so konfiguriert werden, dass sie Lesevorgänge zu einem Zeitstempel in der Vergangenheit ausführen. Schreibgeschützte Transaktionen müssen nicht per Commit übertragen werden und können nicht gesperrt werden. Außerdem können schreibgeschützte Transaktionen warten, bis laufende Schreibvorgänge abgeschlossen sind, bevor sie ausgeführt werden.
Partitionierte DML Dieser Transaktionstyp führt eine DML-Anweisung (Datenbearbeitungssprache) als partitionierte DML aus. Die partitionierte DML ist für Bulk-Aktualisierungen und -Löschvorgänge vorgesehen, insbesondere zum regelmäßigen Bereinigen und Backfilling. Wenn Sie eine große Anzahl von Blind-Writes ausführen müssen, aber keine atomare Transaktion benötigen, können Sie Ihre Spanner-Tabellen mithilfe von Batch Write im Bulk-Verfahren ändern. Weitere Informationen finden Sie unter Daten mit Batch-Schreiben ändern.
Auf dieser Seite werden die allgemeinen Attribute und die Semantik von Transaktionen in Spanner beschrieben. Außerdem werden die nicht schreibgeschützten, schreibgeschützten und partitionierten DML-Transaktionsschnittstellen in Spanner vorgestellt.
Lese-Schreib-Transaktionen
In den folgenden Szenarien sollten Sie Lese-Schreib-Transaktionen sperren:
- Wenn Sie einen Schreibvorgang ausführen, der vom Ergebnis eines oder mehrerer Lesevorgänge abhängt, sollten Sie diesen Schreibvorgang und die Lesevorgänge in derselben Lese-Schreib-Transaktion ausführen.
- Beispiel: Verdoppeln Sie den Kontostand des Bankkontos A. Das Lesen des Kontostands von A sollte in der gleichen Transaktion wie der Schreibvorgang erfolgen, um den Kontostand durch den verdoppelten Wert zu ersetzen.
- Wenn Sie einen oder mehrere Schreibvorgänge ausführen, an denen ein atomarer Commit erforderlich ist, sollten Sie diese Schreibvorgänge in derselben Lese-Schreib-Transaktion ausführen.
- Beispiel: Sie überweisen 200 $ von Konto A zu Konto B. Beide Schreibvorgänge (einer, um A um 200 $ zu verringern, und einer, um B um 200 $ zu erhöhen) und das Lesen der ursprünglichen Kontostände sollten in derselben Transaktion stattfinden.
- Wenn Sie einen oder mehrere Schreibvorgänge ausführen könnten, je nachdem, wie die Ergebnisse eines oder mehrerer Lesevorgänge ausfallen, sollten Sie diese Schreib- und Lesevorgänge in derselben Lese-Schreib-Transaktion ausführen, auch wenn die Schreibvorgänge letztendlich nicht ausgeführt werden.
- Beispiel: Sie überweisen 200 $ vom Bankkonto A zu Bankkonto B, wenn der aktuelle Kontostand von A mehr als 500 $ beträgt. Ihre Transaktion sollte einen Lesevorgang des Kontostands von A und eine bedingte Anweisung enthalten, die die Schreibvorgänge enthält.
Im Folgenden wird ein Szenario beschrieben, in dem Sie keine sperrende Lese-Schreib-Transaktion verwenden sollten:
- Wenn Sie nur Lesevorgänge ausführen und Ihren Lesevorgang mithilfe einer einzelnen Lesemethode ausdrücken können, sollten Sie diese einzelne Lesemethode oder eine schreibgeschützte Transaktion verwenden. Einzelne Lesevorgänge können im Gegensatz zu Lese-Schreib-Transaktionen nicht gesperrt werden.
Attribute
Eine Lese-Schreib-Transaktion in Spanner führt eine Reihe von Lese- und Schreibvorgängen atomisch zu einem einzelnen logischen Zeitpunkt aus. Darüber hinaus entspricht die durch den Zeitstempel angegebene Zeit, zu der Lese-Schreib-Transaktionen ausgeführt werden, der Ortszeit, wobei die Reihenfolge der Serialisierung der Reihenfolge der Zeitstempel entspricht.
Warum sollten Sie eine Lese-Schreib-Transaktion verwenden? Lese-Schreib-Transaktionen bieten die ACID-Attribute von relationalen Datenbanken (tatsächlich bieten Lese-Schreib-Transaktionen in Spanner noch stärkere Garantien als herkömmliche ACID-Transaktionen, siehe Abschnitt Semantik weiter unten).
Isolation
Im Folgenden finden Sie Isolationseigenschaften für Lese-Schreib- und Lese-Transaktionen.
Transaktionen, die Lese- und Schreibvorgänge ausführen
Hier finden Sie die Isolationsattribute, die Sie nach dem erfolgreichen Commit einer Transaktion mit einer Reihe von Lese- (oder Abfragen) und Schreibvorgängen erhalten:
- Alle Lesevorgänge innerhalb der Transaktion haben Werte zurückgegeben, die einen konsistenten Snapshot widerspiegeln, der zum Commit-Zeitstempel der Transaktion aufgenommen wurde.
- Leere Zeilen oder Bereiche blieben zum Zeitpunkt der Commit-Aktion leer.
- Alle Schreibvorgänge innerhalb der Transaktion wurden zum Commit-Zeitstempel der Transaktion durchgeführt.
- Schreibvorgänge waren erst nach dem Commit der Transaktion für alle Transaktionen sichtbar.
Bestimmte Spanner-Client-Treiber enthalten eine Logik zum Wiederholen von Transaktionen, um vorübergehende Fehler zu maskieren. Dazu wird die Transaktion noch einmal ausgeführt und die vom Client beobachteten Daten werden validiert.
Der Effekt besteht darin, dass alle Lese- und Schreibvorgänge zu einem bestimmten Zeitpunkt stattgefunden haben, sowohl aus der Sicht der Transaktion selbst als auch aus der Sicht anderer Leser und Autoren in der Spanner-Datenbank. Anders ausgedrückt: Die Lese- und Schreibvorgänge werden letztendlich zum selben Zeitpunkt ausgeführt (eine Illustration dazu finden Sie im Abschnitt Serialisierbarkeit und externe Konsistenz weiter unten).
Transaktionen, die nur Lesevorgänge ausführen
Die Garantien für eine Lese-Schreib-Transaktion, die nur Lesevorgänge ausführt, sind ähnlich: Alle Lesevorgänge innerhalb dieser Transaktion liefern Daten aus dem gleichen Zeitstempel, auch für Zeilen, die nicht vorhanden sind. Ein Unterschied besteht darin, dass es, wenn Sie Ihre Daten lesen und später einen Commit an der Lese-Schreib-Transaktion ausführen, keine Garantie gibt, dass die Daten innerhalb der Datenbank nach dem Lesen und vor dem Commit modifiziert wurden. Wenn Sie wissen möchten, ob die Daten seit dem letzten Lesevorgang geändert wurden, sollten Sie am besten noch einen Lesevorgang ausführen (entweder in einer Lese-Schreib-Transaktion oder mit einem starken Lesevorgang). Für mehr Effizienz sollten Sie außerdem eine schreibgeschützte Transaktion anstelle einer Lese-Schreib-Transaktion verwenden, wenn Sie bereits im Vorhinein wissen, dass Sie nur Lese- und keine Schreibvorgänge ausführen werden.
Atomarität, Konsistenz, Langlebigkeit
Zusätzlich zum Isolationsattribut bietet Spanner Atomarität (falls ein Commit an einem der Schreibvorgänge in der Transaktion durchgeführt wird, werden Commits an allen durchgeführt), Konsistenz (die Datenbank bleibt nach Abschluss der Transaktion in einem konsistenten Zustand) und Langlebigkeit (übergebene Daten bleiben übergeben).
Vorteile dieser Attribute
Aufgrund dieser Attribute können Sie sich als Anwendungsentwickler auf die Genauigkeit jeder einzelnen Transaktion konzentrieren, ohne sich um den Schutz der ausgeführten Transaktion vor anderen Transaktionen, die möglicherweise zur gleichen Zeit ausgeführt werden könnten, kümmern zu müssen.
Schnittstelle
Die Spanner-Clientbibliotheken bieten eine Schnittstelle zum Ausführen eines Arbeitsablaufs im Zusammenhang mit einer Lese-Schreib-Transaktion, wobei Transaktionsabbrüche wiederholt werden. Dieser Punkt lässt sich mit ein wenig Kontext erläutern: Eine Spanner-Transaktion muss möglicherweise mehrmals getestet werden, bevor sie übergeben werden kann. Wenn beispielsweise zwei Transaktionen versuchen, gleichzeitig mit Daten in einer Weise zu arbeiten, die zu einem Deadlock führen könnte, bricht Spanner eine davon ab, damit die andere Transaktion weiterarbeiten kann. In seltenen Fällen können vorübergehende Ereignisse in Spanner dazu führen, dass einige Transaktionen abgebrochen werden. Da Transaktionen atomar sind, hat eine abgebrochene Transaktion keine Auswirkung auf die Datenbank. Daher sollten Transaktionen so ausgeführt werden, dass sie so lange wiederholt werden, bis sie erfolgreich sind.
Wenn Sie eine Transaktion in einer Spanner-Clientbibliothek verwenden, definieren Sie den Ablauf einer Transaktion (d.h. die Lese- und Schreibvorgänge für eine oder mehrere Tabellen in einer Datenbank) in Form eines Funktionsobjekts. Intern führt die Spanner-Clientbibliothek die Funktion wiederholt aus, bis die Transaktion übergeben wird oder ein nicht wiederholbarer Fehler auftritt.
Beispiel
Beispiel: Sie haben auf der Seite "Schema und Datenmodell" der Tabelle Albums
die Spalte MarketingBudget
hinzugefügt:
CREATE TABLE Albums ( SingerId INT64 NOT NULL, AlbumId INT64 NOT NULL, AlbumTitle STRING(MAX), MarketingBudget INT64 ) PRIMARY KEY (SingerId, AlbumId);
Ihre Marketing-Abteilung beschließt, eine Marketing-Offensive für das Album mit der Kennung Albums (1, 1)
zu starten, und hat Sie gebeten, 200.000 $ aus dem Budget von Albums
(2, 2)
zu übertragen, wenn das Geld im Budget dieses Albums verfügbar ist. Sie sollten für diesen Vorgang eine sperrende Lese-Schreib-Transaktion verwenden, da die Transaktion je nach Ergebnis eines Lesevorgangs Schreibvorgänge ausführen könnte.
Das folgende Beispiel zeigt, wie Sie eine Lese-Schreib-Transaktion ausführen:
C++
C#
Go
Java
Node.js
PHP
Python
Ruby
Semantik
Serialisierbarkeit und externe Konsistenz
Spanner bietet Serialisierbarkeit, das heißt, dass alle Transaktionen so erscheinen, als ob sie in einer seriellen Reihenfolge ausgeführt würden, selbst wenn einige der Lese-, Schreib- und anderen Vorgänge bestimmter Transaktionen tatsächlich parallel stattfanden. Spanner weist Commit-Zeitstempel zu, die der Reihenfolge übernommener Transaktionen entsprechen, um dieses Attribut zu implementieren. Tatsächlich bietet Spanner eine höhere Garantie als Serialisierbarkeit, nämlich externe Konsistenz: Transaktionen werden in einer Reihenfolge übernommen, die von deren Commit-Zeitstempeln widergespiegelt wird. Diese Commit-Zeitstempel spiegeln Echtzeit wider, sodass sie mit Ihrer Uhr verglichen werden können. Lesevorgänge in einer Transaktion erkennen alles, was vor dem Commit der Transaktion übergeben wurde, und Schreibvorgänge werden von allem erkannt, was nach dem Commit der Transaktion gestartet wird.
Angenommen, zwei Transaktionen werden so wie im folgenden Diagramm ausgeführt:
Transaktion Txn1
in Blau liest einige der Daten A
, puffert einen Schreibvorgang in A
und wird erfolgreich übergeben. Transaktion Txn2
in Grün startet nach Txn1
, liest einige der Daten B
und liest dann die Daten A
. Da Txn2
den Wert von A
liest, nachdem Txn1
den Schreibvorgang an A
übergeben hat, erkennt Txn2
die Auswirkung des Schreibvorgangs von Txn1
an A
, obwohl Txn2
gestartet wurde, bevor Txn1
abgeschlossen war.
Auch wenn es zeitliche Überlappungen gibt, in denen Txn1
und Txn2
gleichzeitig ausgeführt werden, gilt für ihre Commit-Zeitstempel c1
und c2
eine lineare Transaktionsreihenfolge. Das heißt, dass alle Auswirkungen der Lese- und Schreibvorgänge von Txn1
scheinbar zu einem einzigen Zeitpunkt (c1
) und alle Auswirkungen der Lese- und Schreibvorgänge von Txn2
scheinbar zu einem einzigen Zeitpunkt (c2
) stattgefunden haben. Darüber hinaus gilt c1 < c2
(dadurch wird garantiert, dass Txn1
und Txn2
Schreibvorgänge übergeben haben; das gilt auch, wenn die Schreibvorgänge auf verschiedenen Geräten ausgeführt wurden), wobei die Reihenfolge Txn1
vor Txn2
berücksichtigt wird.
(Wenn allerdings Txn2
nur Lesevorgänge in der Transaktion ausgeführt hat, gilt c1 <= c2
.)
Lesevorgänge erkennen ein Präfix des Commit-Verlaufs. Wenn ein Lesevorgang die Auswirkung von Txn2
erkennt, erkennt er auch die Auswirkung von Txn1
. Alle Transaktionen, die erfolgreich Commits ausführen, haben dieses Attribut.
Lese- und Schreibgarantien
Wenn ein Aufruf zum Ausführen einer Transaktion fehlschlägt, hängen Ihre Lese- und Schreibgarantien davon ab, welcher Fehler beim zugrunde liegenden Commit-Aufruf für das Fehlschlagen verantwortlich war.
Zum Beispiel bedeutet das Auftreten eines Fehlers der Art "Zeile nicht gefunden" oder "Zeile existiert bereits", dass beim Schreiben der gepufferten Mutationen ein Fehler aufgetreten ist, z. B. dass eine Zeile, die der Client zu aktualisieren versucht, nicht vorhanden ist. In diesem Fall sind die Lesevorgänge garantiert konsistent, die Schreibvorgänge werden nicht angewendet und das Nicht-Vorhandensein einer Zeile ist ebenfalls mit den Lesevorgängen garantiert konsistent.
Transaktionen abbrechen
Asynchrone Leseoperationen können jederzeit vom Nutzer abgebrochen werden (z. B., wenn eine Operation auf höherer Ebene abgebrochen wird oder Sie entscheiden, einen Lesevorgang basierend auf den ersten Ergebnissen zu stoppen, die vom Lesevorgang empfangen wurden), ohne andere existierende Operationen innerhalb der Transaktion zu beeinflussen.
Auch wenn Sie versucht haben, den Lesevorgang abzubrechen, garantiert Spanner nicht, dass der Lesevorgang tatsächlich abgebrochen wird. Nachdem Sie den Abbruch eines Lesevorgangs angefordert haben, kann dieser Lesevorgang immer noch erfolgreich abgeschlossen werden oder aus einem anderen Grund fehlschlagen (z. B. Abbruch). Darüber hinaus kann der abgebrochene Lesevorgang noch einige Ergebnisse liefern. Diese möglicherweise unvollständigen Ergebnisse werden als Teil des Transaktions-Commits validiert.
Beachten Sie, dass im Gegensatz zu Lesevorgängen das Abbrechen eines Transaktion-Commit-Vorgangs zum Abbruch der Transaktion führt (es sei denn, die Transaktion wurde bereits übergeben oder ist aus einem anderen Grund fehlgeschlagen).
Leistung
Sperren
Mit Spanner können mehrere Clients gleichzeitig mit derselben Datenbank interagieren. Damit die Konsistenz der vielen simultanen Transaktionen garantiert wird, verwendet Spanner eine Kombination von gemeinsamen Sperren und exklusiven Sperren, um den Zugriff auf die Daten zu steuern. Wenn Sie einen Lesevorgang als Teil einer Transaktion ausführen, erfasst Spanner gemeinsam genutzte Lesesperren, wodurch andere Lesevorgänge weiterhin auf die Daten zugreifen können, bis die Transaktion zum Commit bereit ist. Wenn sich Ihre Transaktion im Commit befindet und Schreibvorgänge angewendet werden, versucht die Transaktion, ein Upgrade auf eine exklusive Sperre auszuführen. Sie blockiert neue gemeinsam genutzte Lesesperren für die Daten, wartet darauf, dass vorhandene gemeinsam genutzte Lesesperren bereinigt werden, und setzt eine exklusive Sperre für den exklusiven Zugriff auf die Daten ein.
Hinweise zu Sperren:
- Sperren werden mit der Granularität von Zeile und Spalte vorgenommen. Wenn mit der Transaktion T1 die Spalte "A" der Zeile "foo" gesperrt wurde und mit Transaktion T2 die Spalte "B" der Zeile "foo" geschrieben werden soll, besteht kein Konflikt.
- Schreibvorgänge in einem Datenelement, das nicht auch die Daten liest, die gerade geschrieben werden (auch "blind writes" genannt) stehen in keinem Konflikt zu anderen Blind Writers desselben Elements (der Commit-Zeitstempel der einzelnen Schreibvorgänge bestimmt die Reihenfolge, in der er auf die Datenbank angewendet wird). Eine Konsequenz daraus ist, dass Spanner nur ein Upgrade auf eine exklusive Sperre ausführen muss, wenn Sie die Daten, die Sie schreiben, gelesen haben. Andernfalls verwendet Spanner eine gemeinsam genutzte Sperre, die als vom Autor gemeinsam genutzte Sperre bezeichnet wird.
- Wenn Sie einzelne Suchvorgänge innerhalb einer Lese-Schreib-Transaktion ausführen, begrenzen Sie die Anzahl der durchsuchten Zeilen mit sekundären Indexen. Dies führt dazu, dass Spanner weniger Zeilen in der Tabelle sperrt, was eine gleichzeitige Änderung an Zeilen außerhalb des Bereichs zulässt.
Sperren sollten nicht verwendet werden, um den exklusiven Zugriff auf eine Ressource außerhalb von Spanner zu gewährleisten. Transaktionen können aus verschiedenen Gründen von Spanner abgebrochen werden, z. B. wenn Daten in die Rechenressourcen der Instanz verschoben werden können. Wenn eine Transaktion entweder explizit durch Anwendungscode oder implizit durch Clientcode wie den Spanner JDBC-Treiber wiederholt wird, wird nur garantiert, dass die Sperren während des tatsächlichen Versuchs bestanden haben.
Mit dem Introspektionstool zum Sperren von Statistiken können Sie Sperrkonflikte in Ihrer Datenbank untersuchen.
Deadlock-Erkennung
Spanner erkennt, wenn mehrere Transaktionen blockiert werden, und zwingt alle bis auf eine der Transaktionen zum Abbrechen. Betrachten Sie zum Beispiel das folgende Szenario: Transaktion Txn1
enthält eine Sperre für Datensatz A
und wartet auf eine Sperre für Datensatz B
. Txn2
enthält eine Sperre für Datensatz B
und wartet auf eine Sperre für Datensatz A
. Die einzige Möglichkeit, in dieser Situation voranzukommen, besteht darin, eine der Transaktionen abzubrechen, damit die Sperre freigegeben wird und die andere Transaktion fortgesetzt werden kann.
Spanner verwendet den Standardalgorithmus „wound-wait“ für die Deadlock-Erkennung. Spanner verfolgt das Alter jeder Transaktion, die in Konflikt stehende Sperren anfordert. Es ermöglicht älteren Transaktionen, jüngere Transaktionen abzubrechen (wobei "älter" heißt, dass die frühesten Lese-, Abfrage- oder Commit-Vorgänge der Transaktion früher begonnen haben).
Dadurch, dass ältere Transaktionen Priorität erhalten, sorgt Spanner dafür, dass jede Transaktion die Möglichkeit bekommt, Sperren zu erhalten, nachdem sie alt genug ist, um Priorität vor anderen Transaktionen zu bekommen. Zum Beispiel kann eine Transaktion, die eine vom Leser freigegebene Sperre erhält, von einer älteren Transaktion abgebrochen werden, die eine vom Autor freigegebene Sperre benötigt.
Verteilte Ausführung
Spanner kann Transaktionen für Daten ausführen, die sich über mehrere Server erstrecken. Diese Leistung führt zu Leistungskosten, die mit denen von Transaktionen auf nur einem Server zu vergleichen sind.
Welche Arten von Transaktionen können verteilt sein? Intern kann Spanner die Verantwortung für Zeilen in der Datenbank auf mehrere Server verteilen. Eine Zeile und die entsprechenden Zeilen in verschränkten Tabellen werden in der Regel von demselben Server verarbeitet, so wie bei zwei Zeilen in derselben Tabelle mit ähnlichen Schlüsseln. Spanner kann Transaktionen mit Zeilen über mehrere Server ausführen. Allerdings gilt als Faustregel, dass Transaktionen, die viele Zeilen an einem Standort betreffen, schneller und günstiger sind als Transaktionen, die viele in der Datenbank oder in einer großen Tabelle verteilte Zeilen betreffen.
Zu den effizientesten Transaktionen in Spanner gehören nur Lese- und Schreibvorgänge, die atomar angewendet werden sollen. Transaktionen sind am schnellsten, wenn alle Lese- und Schreibzugriffe auf Daten im selben Teil des Schlüsselbereichs erfolgen.
Schreibgeschützte Transaktionen
Zusätzlich zu sperrenden Lese-Schreib-Transaktionen bietet Spanner schreibgeschützte Transaktionen.
Verwenden Sie eine schreibgeschützte Transaktion, wenn Sie mehr als einen Lesevorgang mit demselben Zeitstempel ausführen müssen. Wenn Sie Ihren Lesevorgang mithilfe einer einzelnen Lesemethode von Spanner ausdrücken können, sollten Sie stattdessen diese einzelne Lesemethode verwenden. Die Leistung bei der Verwendung eines solchen einzelnen Leseaufrufs sollte mit der Leistung eines einzelnen Lesevorgangs vergleichbar sein, der in einer schreibgeschützten Transaktion ausgeführt wird.
Wenn Sie eine große Datenmenge lesen, sollten Sie Partitionen verwenden, um die Daten parallel zu lesen.
Da schreibgeschützte Transaktionen keine Schreibvorgänge ausführen, haben sie keine Sperren und blockieren andere Transaktionen nicht. Schreibgeschützte Transaktionen erkennen ein konsistentes Präfix des Commit-Verlaufs der Transaktion, damit Ihre Anwendung immer konsistente Daten erhält.
Attribute
Eine schreibgeschützte Transaktion in Spanner führt eine Reihe von Lese- und Schreibvorgängen zu einem einzigen logischen Zeitpunkt aus, sowohl aus der Sicht der schreibgeschützten Transaktion selbst als auch aus der Perspektive anderer Leser und Autoren in der Spanner-Datenbank. Dies bedeutet, dass schreibgeschützte Transaktionen immer einen konsistenten Zustand der Datenbank zu einem ausgewählten Punkt im Transaktionsverlauf erkennen.
Schnittstelle
Spanner bietet eine Schnittstelle zum Ausführen eines Arbeitsablaufs im Rahmen einer schreibgeschützten Transaktion mit Wiederholungen für Transaktionsabbrüche.
Beispiel
Im Folgenden wird gezeigt, wie eine schreibgeschützte Transaktion verwendet werden kann, um konsistente Daten für zwei Lesevorgänge zum selben Zeitstempel zu erhalten:
C++
C#
Go
Java
Node.js
PHP
Python
Ruby
Partitionierte DML-Transaktionen
Mit partitionierten DML-Anweisungen (Partitioned Data Manipulation Language) können Sie umfangreiche Anweisungen des Typs UPDATE
und DELETE
ausführen, ohne die Transaktionslimits zu überschreiten oder eine ganze Tabelle zu sperren.
Spanner partitioniert den Schlüsselbereich und führt die DML-Anweisungen in jeder Partition in einer separaten Lese-/Schreibtransaktion aus.
Sie führen DML-Anweisungen in Lese-/Schreibtransaktionen aus, die Sie explizit in Ihrem Code erstellen. Weitere Informationen finden Sie unter DML verwenden.
Attribute
Sie können jeweils nur eine partitionierte DML-Anweisung ausführen, unabhängig davon, ob Sie eine Clientbibliotheksmethode oder die Google Cloud CLI verwenden.
Partitionierte Transaktionen unterstützen kein Commit oder Rollback. Spanner führt die DML-Anweisung sofort aus und wendet sie an. Wenn Sie den Vorgang abbrechen oder der Vorgang fehlschlägt, bricht Spanner alle ausgeführten Partitionen ab und startet keine der verbleibenden Partitionen. Spanner führt für bereits ausgeführte Partitionen kein Rollback aus.
Schnittstelle
Spanner bietet eine Schnittstelle zum Ausführen einer einzelnen partitionierten DML-Anweisung.
Beispiele
Mit den folgenden Codebeispielen wird die Spalte MarketingBudget
der Tabelle Albums
aktualisiert.
C++
Zum Ausführen einer partitionierten DML-Anweisung verwenden Sie die Funktion ExecutePartitionedDml()
.
C#
Zum Ausführen einer partitionierten DML-Anweisung verwenden Sie die Methode ExecutePartitionedUpdateAsync()
.
Go
Zum Ausführen einer partitionierten DML-Anweisung verwenden Sie die Methode PartitionedUpdate()
.
Java
Zum Ausführen einer partitionierten DML-Anweisung verwenden Sie die Methode executePartitionedUpdate()
.
Node.js
Zum Ausführen einer partitionierten DML-Anweisung verwenden Sie die Methode runPartitionedUpdate()
.
PHP
Zum Ausführen einer partitionierten DML-Anweisung verwenden Sie die Methode executePartitionedUpdate()
.
Python
Zum Ausführen einer partitionierten DML-Anweisung verwenden Sie die Methode execute_partitioned_dml()
.
Ruby
Zum Ausführen einer partitionierten DML-Anweisung verwenden Sie die Methode execute_partitioned_update()
.
Im folgenden Codebeispiel werden Zeilen aus der Tabelle Singers
anhand der Spalte SingerId
gelöscht.