Transaktionen

Eine Transaktion besteht aus SQL-Anweisungen (Lese- und Schreiboperationen), die als Einheit verarbeitet werden. Alle Anweisungen in der Transaktion werden entweder angewendet (d. h. Commit) oder rückgängig gemacht (d. h. Rollback). Die Transaktion kann sowohl Lese- als auch Schreibvorgänge umfassen. Ähnlich wie andere Datenbanken garantieren Snowflake-Transaktionen ACID-Eigenschaften.

Unter diesem Thema:

Umfang einer Snowflake-Transaktion

Eine Transaktion ist einer einzelnen Sitzung zugeordnet. Mehrere Sitzungen können nicht dieselbe Transaktion teilen.

Eine Transaktion kann explizit gestartet werden, indem eine BEGIN-Anweisung ausgeführt wird. Eine Transaktion kann implizit in folgenden Situationen gestartet werden:

  • Nachdem AUTOCOMMIT deaktiviert wurde, startet die nächste DML-Anweisung (falls vorhanden) implizit eine Transaktion.

  • Während AUTOCOMMIT deaktiviert ist, startet die erste DML-Anweisung (falls vorhanden) nach COMMIT oder ROLLBACK implizit eine Transaktion.

Nachdem eine Transaktion gestartet wurde, muss sie mit der Anweisung COMMIT oder ROLLBACK abgeschlossen werden. Wenn eine Sitzung mit einer offenen Transaktion geschlossen wird, wird die offene Transaktion zurückgesetzt.

Wenn sich der AUTOCOMMIT-Status ändert (von „false“ in „true“ oder umgekehrt), wird die aktuell ausgeführte Transaktion mit COMMIT abgeschlossen.

Jeder Snowflake-Transaktion wird eine eindeutige Startzeit (einschließlich Millisekunden) zugewiesen, die als ID für die Transaktion dient. Beispiele für Startzeiten von Transaktionen finden Sie in den Beispielen für BEGIN.

Autocommit

Standardmäßig wird eine DML-Anweisung, die ohne explizites Starten einer Transaktion ausgeführt wird, bei Erfolg automatisch committet oder bei einem Fehler am Ende der Anweisung zurückgesetzt. Dieses Verhalten wird als Autocommit bezeichnet. Dieses Verhalten wird mit dem Parameter AUTOCOMMIT gesteuert.

DDL-Anweisungen werden unabhängig von der AUTOCOMMIT-Einstellung immer automatisch committet. Das Ausführen einer DDL-Anweisung innerhalb einer offenen Transaktion bewirkt Folgendes:

  • Führt ein Commit der geöffneten Transaktion aus.

  • Führt die DDL-Anweisung aus, und führt dann ein Commit aus.

CTAS-Anweisungen (CREATE TABLE AS SELECT ...) werden wie DDL behandelt und werden daher automatisch committet.

Da eine DDL-Anweisung eine eigene Transaktion ist, können Sie eine DDL-Anweisung auch nicht rückgängig machen. Die Transaktion, die die DDL enthält, wird abgeschlossen, bevor Sie ein ROLLBACK ausführen können. Um DDL-Anweisungen rückgängig zu machen, müssen Sie meist eine andere DDL-Anweisung ausführen (z. B. DROP für eine erstellte Tabelle, ALTER um eine vorher geänderte Tabelle wieder auf den ursprünglichen Stand zurücksetzen, oder UNDROP eines Objekts, das Sie vorher gelöscht hatten).

Rollback von Anweisungen

Wenn eine DML-Anweisung, die in einer explizit gestarteten Transaktion ausgeführt wird, fehlschlägt, werden die mit DML vorgenommenen Änderungen rückgängig gemacht. Die Transaktion bleibt jedoch offen, bis für die Transaktion ein Commit oder Rollback ausgeführt wird.

Transaktionen und Multithreading

Obwohl mehrere Sitzungen nicht dieselbe Transaktion gemeinsam nutzen können, teilen sich mehrere Threads, die eine einzelne Verbindung verwenden, dieselbe Sitzung und somit dieselbe Transaktion. Dies kann zu unerwarteten Ergebnissen führen, z. B. wenn ein Thread ein Rollback einer Arbeit vornimmt, die in einem anderen Thread ausgeführt wird.

Diese Situation kann auftreten, wenn eine Clientanwendung, die einen Snowflake-Treiber (z. B. den Snowflake-JDBC-Treiber) oder einen Konnektor (z. B. den Snowflake-Konnektor für Python) verwendet, über mehrere Threads verfügt. Wenn zwei oder mehr Threads dieselbe Verbindung verwenden, teilen sich diese Threads auch die aktuelle Transaktion in dieser Verbindung. Ein BEGIN, COMMIT oder ROLLBACK von einem Thread wirkt sich auf alle Threads aus, die diese gemeinsam genutzte Verbindung verwenden. Wenn die Threads asynchron ausgeführt werden, können die Ergebnisse unvorhersehbar sein.

Ebenso wirkt sich das Ändern der AUTOCOMMIT-Einstellung in einem Thread auf die AUTOCOMMIT-Einstellung in allen anderen Threads aus, die dieselbe Verbindung verwenden.

Beachten Sie, dass das Ändern des Status der AUTOCOMMIT-Einstellung zum COMMIT einer vorhandenen Transaktion führt.

Snowflake empfiehlt, dass Multithread-Clientprogramme mindestens eine der folgenden Aktionen ausführen:

  • Verwenden Sie für jeden Thread eine separate Verbindung.

    Beachten Sie aber, dass Ihr Code auch bei separaten Verbindungen in Wettlaufsituationen (Racebedingungen) gelangen kann, die unvorhersehbare Ausgaben generieren. Beispielsweise kann ein Thread Daten löschen, bevor ein anderer Thread versucht, diese zu aktualisieren.

  • Führen Sie die Threads nicht asynchron, sondern synchron aus, um die Reihenfolge zu steuern, in der die Schritte ausgeführt werden.

Isolationsebene

Snowflake-Transaktionen unterstützen die READ COMMITTED-Isolation für Tabellen. READ COMMITTED ist die derzeit einzige unterstützte Isolationsebene für Tabellen.

READ COMMITTED-Isolation

Bei der READ COMMITTED-Isolation „sieht“ eine Anweisung nur Daten, für die vor Beginn der Anweisung ein Commit ausgeführt wurde. Die Anweisung wird niemals Daten sehen, für die kein Commit ausgeführt wurde.

Wenn eine Anweisung innerhalb einer Transaktion mit mehreren Anweisungen ausgeführt wird:

  • Eine Anweisung sieht nur Daten, für die vor Ausführungsbeginn der Anweisung Commit ausgeführt wurde. Zwei aufeinanderfolgende Anweisungen in derselben Transaktion können unterschiedliche Daten sehen, wenn zwischen der Ausführung der ersten und der zweiten Anweisung eine andere Transaktion ein Commit ausführt.

  • Eine Anweisung sieht jedoch die Änderungen, die von vorherigen Anweisungen innerhalb derselben Transaktion ausgeführt wurden, auch wenn diese Änderungen noch nicht mit Commit bestätigt wurden.

Ressourcensperrung

Transaktionsoperationen rufen Sperren für eine Ressource ab, z. B. eine Tabelle, während diese Ressource geändert wird. Sperren sorgen dafür, dass andere Anweisungen die Ressource erst ändern können, wenn die Sperre aufgehoben wurde.

In den meisten Situationen gelten folgende Richtlinien:

  • COMMIT-Operationen (einschließlich Autocommit und expliziter COMMIT) sperren Ressourcen, aber meist nur für kurze Zeit.

  • Bei UPDATE-, DELETE- und MERGE-Anweisungen werden Sperren aufrechterhalten, damit nicht gleichzeitig andere UPDATE-, DELETE- und MERGE-Anweisungen ausgeführt werden können.

  • Die meisten INSERT- und COPY-Anweisungen schreiben nur in neue Partitionen. Diese Anweisungen können daher meist parallel zu anderen INSERT- und COPY-Operationen und manchmal auch parallel zu einer UPDATE-, DELETE- oder MERGE-Anweisung ausgeführt werden.

Sperren, die von einer Anweisung aufrechterhalten werden, werden erst bei COMMIT oder ROLLBACK der Transaktion freigegeben.

Wartezeit-Timeout für Sperren

Eine blockierte Anweisung ruft entweder eine Sperre für die Ressource ab, auf die sie gewartet hat, oder ein Timeout für die Wartezeit bis zur Freigabe der Ressource. Die Zeit (in Sekunden), die eine Anweisung gesperrt werden soll, kann durch Setzen des Parameters LOCK_TIMEOUT konfiguriert werden.

So ändern Sie beispielsweise das Sperrzeitlimit für die aktuelle Sitzung auf 2 Stunden (7.200 Sekunden):

ALTER SESSION SET LOCK_TIMEOUT=7200;

SHOW PARAMETERS LIKE 'lock%';

+--------------+-------+---------+---------+-------------------------------------------------------------------------------+
| key          | value | default | level   | description                                                                   |
|--------------+-------+---------+---------+-------------------------------------------------------------------------------|
| LOCK_TIMEOUT | 7200  | 43200   | SESSION | Number of seconds to wait while trying to lock a resource, before timing out  |
|              |       |         |         | and aborting the statement. A value of 0 turns off lock waiting i.e. the      |
|              |       |         |         | statement must acquire the lock immediately or abort. If multiple resources   |
|              |       |         |         | need to be locked by the statement, the timeout applies separately to each    |
|              |       |         |         | lock attempt.                                                                 |
+--------------+-------+---------+---------+-------------------------------------------------------------------------------+

Deadlocks

Deadlocks treten auf, wenn gleichzeitig laufende Transaktionen auf Ressourcen warten, die sich gegenseitig gesperrt haben.

In Snowflake kann es nicht zu einem Deadlock kommen, wenn gleichzeitig Autocommit-DML-Anweisungen ausgeführt werden. Deadlocks können jedoch bei explizit gestarteten Transaktionen und mehreren Anweisungen in jeder Transaktion auftreten. Snowflake erkennt Deadlocks und wählt die neueste Anweisung, die Teil des Deadlocks ist, als Opfer. Die Anweisung wird zurückgesetzt, aber die Transaktion selbst bleibt offen und muss committet oder zurückgesetzt werden.

Zulassen des Abbrechens von Transaktionen bei Anweisungsfehlern

Damit ein Anweisungsfehler innerhalb einer Transaktion die Transaktion abbrechen kann, legen Sie den Parameter TRANSACTION_ABORT_ON_ERROR auf Sitzungs- oder Kontoebene fest.

Transaktionsbefehle und -funktionen

Snowflake bietet die folgenden SQL-Befehle zur Unterstützung von Transaktionen:

Darüber hinaus bietet Snowflake die folgenden Kontextfunktionen zum Abrufen von Informationen zu den Transaktionen einer Sitzung:

Abbrechen von Transaktionen

Wenn in einer Sitzung eine Transaktion ausgeführt und die Sitzung abrupt unterbrochen wird, um zu verhindern, dass für die Transaktion ein Commit oder Rollback ausgeführt wird, verbleibt die Transaktion im getrennten Zustand, einschließlich aller Sperren, die die Transaktion auf Ressourcen hält. Wenn dies geschieht, müssen Sie die Transaktion möglicherweise abbrechen.

Um eine laufende Transaktion abzubrechen, kann der Benutzer, der die Transaktion gestartet hat, oder ein Kontoadministrator die Systemfunktion SYSTEM$ABORT_TRANSACTION aufrufen.

Wenn die Transaktion offen bleibt, setzt Snowflake die Transaktion in der Regel zurück, nachdem sie vier Stunden lang inaktiv war.