Cursorsperren

In MicrosoftSQL Server unterliegt die SELECT-Anweisung in einer Cursordefinition denselben Regeln, die auch für das Sperren von anderen SELECT-Anweisungen gelten. Bei Cursorn kann jedoch eine zusätzliche Reihe von Scrollsperren auf der Grundlage der Spezifikation einer Cursorparallelitätsstufe eingerichtet werden.

Die Transaktionssperren, die von jeder SELECT-Anweisung abgerufen werden können, einschließlich der SELECT-Anweisung in einer Cursordefinition, werden durch folgende Elemente gesteuert:

  • Die Einstellung der Transaktionsisolationsstufe für die Verbindung.

  • Alle in der FROM-Klausel angegebenen Sperrhinweise.

Diese Sperren werden bis an das Ende der aktuellen Transaktion sowohl für Cursor als auch für unabhängige SELECT-Anweisungen aufrechterhalten. Wenn SQL Server im Autocommitmodus ausgeführt wird, ist jede einzelne SQL-Anweisung eine Transaktion, und die Sperren werden freigegeben, nachdem die jeweilige Anweisung beendet wurde. Wenn SQL Server im expliziten oder impliziten Transaktionsmodus ausgeführt wird, werden alle Sperren aufrechterhalten, bis entweder ein Commit oder ein Rollback für die Transaktion ausgeführt wird.

So ist beispielsweise der Sperrvorgang für diese beiden Transact-SQL-Beispiele im Wesentlichen identisch:

/* Example 1 */
SET TRANSACTION ISOLATION LEVEL REPEATABLE READ
GO
BEGIN TRANSACTION
GO
SELECT * FROM AdventureWorks.Sales.Store;
GO

/* Example 2 */
SET TRANSACTION ISOLATION LEVEL REPEATABLE READ
GO
BEGIN TRANSACTION
GO
DECLARE abc CURSOR STATIC FOR
SELECT * FROM AdventureWorks.Sales.Store;
GO
OPEN abc
GO

Wird die Transaktionsisolationsstufe auf REPEATABLE READ festgelegt, bedeutet dies, dass sowohl die unabhängige SELECT-Anweisung in Beispiel 1 als auch die in DECLARE CURSOR aus Beispiel 2 enthaltene SELECT-Anweisung freigegebene Sperren für jede gelesene Zeile generieren und dass diese freigegebenen Sperren aufrechterhalten werden, bis ein Commit oder ein Rollback für die Transaktion ausgeführt wird.

Abrufen von Sperren

Obwohl Cursor denselben Regeln wie unabhängige SELECT-Anweisungen im Hinblick auf den Typ der abgerufenen Transaktionssperre folgen, werden die Sperren zu unterschiedlichen Zeiten abgerufen. Die von einer unabhängigen SELECT-Anweisung oder einem Cursor generierten Sperren werden immer dann abgerufen, wenn eine Zeile abgerufen wird. Bei einer unabhängigen SELECT-Anweisung werden alle Zeilen abgerufen, wenn die Anweisung ausgeführt wird. Cursor rufen die Zeilen jedoch abhängig vom Cursortyp zu unterschiedlichen Zeiten ab:

  • Statische Cursor rufen das gesamte Resultset zum Zeitpunkt des Öffnens des Cursors ab. Dadurch wird jede Zeile des Resultsets zum Zeitpunkt des Öffnens gesperrt.

  • Keysetgesteuerte Cursor rufen die Schlüssel jeder Zeile des Resultsets zum Zeitpunkt des Öffnens des Cursors ab. Dadurch wird jede Zeile des Resultsets zum Zeitpunkt des Öffnens gesperrt.

  • Dynamische Cursor (einschließlich normaler Vorwärtscursor) rufen Zeilen erst ab, wenn sie per FETCH-Anweisung angefordert werden. Für die Zeilen sind so lange keine Sperren abgerufen, bis sie mit FETCH abgerufen werden.

  • Schnelle Vorwärtscursor können ihre Sperren zu unterschiedlichen Zeitpunkten abrufen. Der jeweilige Zeitpunkt hängt von dem vom Abfrageoptimierer ausgewählten Ausführungsplan ab. Falls ein dynamischer Plan ausgewählt wird, werden Sperren erst dann vorgenommen, wenn die Zeilen abgerufen werden. Werden Arbeitstabellen generiert, so werden die Zeilen in die Arbeitstabelle eingelesen und zum Zeitpunkt des Öffnens gesperrt.

Cursor unterstützen zusätzlich ihre eigenen Parallelitätsspezifikationen. Einige dieser Parallelitätsspezifikationen generieren bei jeder Abrufoperation zusätzliche Sperren für die Zeilen. Diese Scrollsperren werden bis zur nächsten Abrufoperation aufrechterhalten oder so lange, bis der Cursor geschlossen wird, je nachdem, welches Ereignis zuerst eintritt. Wenn die Verbindungsoption, Cursor bei einem Commit geöffnet zu halten, aktiviert ist, werden diese Sperren auch bei einem Commit- oder einem Rollbackvorgang aufrechterhalten.