Momentaufnahmenisolation in SQL ServerSnapshot Isolation in SQL Server

Die Momentaufnahmeisolation erweitert die Parallelität für OLTP-Anwendungen.Snapshot isolation enhances concurrency for OLTP applications.

Informationen zur Snapshot-Isolation und ZeilenversionserstellungUnderstanding Snapshot Isolation and Row Versioning

Nach Aktivierung der Snapshot-Isolation werden aktuelle Zeilenversionen für jede Transaktion in verwaltet Tempdb.Once snapshot isolation is enabled, updated row versions for each transaction are maintained in tempdb. Jede Transaktion wird durch eine Transaktionsfolgenummer gekennzeichnet, und diese eindeutigen Nummern werden für jede Zeilenversion aufgezeichnet.A unique transaction sequence number identifies each transaction, and these unique numbers are recorded for each row version. Für die Transaktion werden die aktuellsten Zeilenversionen verwendet, die über eine Folgenummer verfügen, die niedriger ist als diejenige der Transaktion.The transaction works with the most recent row versions having a sequence number before the sequence number of the transaction. Aktuellere, nach dem Beginn der Transaktion erstellte Zeilenversionen werden von der Transaktion ignoriert.Newer row versions created after the transaction has begun are ignored by the transaction.

Die Benennung "Momentaufnahme" gibt die Tatsache wieder, dass alle Abfragen in der Transaktion auf dieselbe Version (Momentaufnahme) der Datenbank zurückgehen, die auf dem Zustand der Datenbank zum Zeitpunkt des Beginns der Transaktion basiert.The term "snapshot" reflects the fact that all queries in the transaction see the same version, or snapshot, of the database, based on the state of the database at the moment in time when the transaction begins. In einer Snapshot-Transaktion werden für die zugrunde liegenden Datenzeilen oder Datenseiten keine Sperren bezogen, wodurch andere Transaktionen ausgeführt werden können, ohne durch eine vorherige, nicht vollständig ausgeführte Transaktion blockiert zu werden.No locks are acquired on the underlying data rows or data pages in a snapshot transaction, which permits other transactions to execute without being blocked by a prior uncompleted transaction. Transaktionen, die Daten ändern, blockieren keine Transaktionen, die Daten lesen; und Transaktionen, die Daten lesen, blockieren keine Transaktionen, die Daten schreiben. Bei der READ COMMITTED-Standardisolationsstufe in SQL Server wäre dies i. d. R. der Fall.Transactions that modify data do not block transactions that read data, and transactions that read data do not block transactions that write data, as they normally would under the default READ COMMITTED isolation level in SQL Server. Dieses nicht blockierende Verhalten verringert die Wahrscheinlichkeit für Deadlocks bei komplexen Transaktionen beträchtlich.This non-blocking behavior also significantly reduces the likelihood of deadlocks for complex transactions.

Bei der Snapshot-Isolation wird ein Modell der vollständigen Parallelität verwendet.Snapshot isolation uses an optimistic concurrency model. Wenn eine Snapshot-Transaktion versucht, Änderungen an Daten zu speichern, die seit dem Beginn der Transaktion geändert wurden, wird die Transaktion zurückgesetzt und ein Fehler ausgelöst.If a snapshot transaction attempts to commit modifications to data that has changed since the transaction began, the transaction will roll back and an error will be raised. Dies kann durch das Verwenden von UPDLOCK-Hinweisen für SELECT-Anweisungen verhindert werden, die auf zu ändernde Daten zugreifen.You can avoid this by using UPDLOCK hints for SELECT statements that access data to be modified. Weitere Informationen finden Sie in der Onlinedokumentation zu SQL Server unter "Locking Hints".See "Locking Hints" in SQL Server Books Online for more information.

Die Snapshot-Isolation muss durch das Festlegen der ALLOW_SNAPSHOT_ISOLATION ON-Datenbankoption aktiviert werden, bevor sie in Transaktionen verwendet wird.Snapshot isolation must be enabled by setting the ALLOW_SNAPSHOT_ISOLATION ON database option before it is used in transactions. Dies aktiviert den Mechanismus zum Speichern von Zeilenversionen in der temporären Datenbank (Tempdb).This activates the mechanism for storing row versions in the temporary database (tempdb). Die Snapshot-Isolation muss in jeder Datenbank, die diese verwendet, mit der ALTER DATABASE-Transact-SQL-Anweisung aktiviert werden.You must enable snapshot isolation in each database that uses it with the Transact-SQL ALTER DATABASE statement. In diesem Punkt unterscheidet sich die Snapshot-Isolation von den herkömmlichen Isolationsstufen READ COMMITTED, REPEATABLE READ, SERIALIZABLE und READ UNCOMMITTED, für die keine Konfiguration erforderlich ist.In this respect, snapshot isolation differs from the traditional isolation levels of READ COMMITTED, REPEATABLE READ, SERIALIZABLE, and READ UNCOMMITTED, which require no configuration. Die folgenden Anweisungen aktivieren die Snapshot-Isolation und ersetzen das READ COMMITTED-Standardverhalten durch SNAPSHOT:The following statements activate snapshot isolation and replace the default READ COMMITTED behavior with SNAPSHOT:

ALTER DATABASE MyDatabase  
SET ALLOW_SNAPSHOT_ISOLATION ON  

ALTER DATABASE MyDatabase  
SET READ_COMMITTED_SNAPSHOT ON  

Das Festlegen der READ_COMMITTED_SNAPSHOT ON-Option ermöglicht Zugriff auf versionierte Zeilen mit der READ COMMITTED-Isolationsstufe.Setting the READ_COMMITTED_SNAPSHOT ON option allows access to versioned rows under the default READ COMMITTED isolation level. Wenn die READ_COMMITTED_SNAPSHOT-Option auf OFF festgelegt ist, müssen Sie die Snapshot-Isolationsstufe für jede Sitzung explizit festlegen, um auf versionierte Zeilen zuzugreifen.If the READ_COMMITTED_SNAPSHOT option is set to OFF, you must explicitly set the Snapshot isolation level for each session in order to access versioned rows.

Verwalten von Parallelität mit IsolationsstufenManaging Concurrency with Isolation Levels

Die Isolationsstufe, mit der eine Transact-SQL-Anweisung ausgeführt wird, bestimmt das entsprechende Verhalten bei der Sperr- und Zeilenversionserstellung.The isolation level under which a Transact-SQL statement executes determines its locking and row versioning behavior. Eine Isolationsstufe gilt für die gesamte Verbindung, und sobald sie mit der SET TRANSACTION ISOLATION LEVEL-Anweisung für eine Verbindung festgelegt wurde, bleibt sie aktiv, bis die Verbindung geschlossen oder eine andere Isolationsstufe festgelegt wird.An isolation level has connection-wide scope, and once set for a connection with the SET TRANSACTION ISOLATION LEVEL statement, it remains in effect until the connection is closed or another isolation level is set. Wenn eine Verbindung geschlossen und an den Pool zurückgegeben wird, wird die Isolationsstufe aus der letzten SET TRANSACTION ISOLATION LEVEL-Anweisung beibehalten.When a connection is closed and returned to the pool, the isolation level from the last SET TRANSACTION ISOLATION LEVEL statement is retained. Nachfolgende Verbindungen, die eine an den Pool zurückgegebene Verbindung erneut verwenden, verwenden die Isolationsstufe, die zu dem Zeitpunkt gültig war, als die Verbindung an den Pool zurückgegeben wurde.Subsequent connections reusing a pooled connection use the isolation level that was in effect at the time the connection is pooled.

Einzelne innerhalb einer Verbindung durchgeführte Abfragen können Sperrhinweise enthalten, die die Isolation für eine einzelne Anweisung oder Transaktion ändern, aber die Isolationsstufe der Verbindung nicht beeinflussen.Individual queries issued within a connection can contain lock hints that modify the isolation for a single statement or transaction but do not affect the isolation level of the connection. Isolationsstufen oder Sperrhinweise, die in gespeicherten Prozeduren oder Funktionen festgelegt sind, ändern die Isolationsstufe der aufrufenden Verbindung nicht. Sie sind nur für die Dauer der gespeicherten Prozedur oder des Funktionsaufrufs aktiv.Isolation levels or lock hints set in stored procedures or functions do not change the isolation level of the connection that calls them and are in effect only for the duration of the stored procedure or function call.

In frühen Versionen von SQL Server wurden vier Isolationsstufen unterstützt, die im SQL-92-Standard definiert wurden:Four isolation levels defined in the SQL-92 standard were supported in early versions of SQL Server:

  • READ UNCOMMITTED ist die am wenigsten restriktive Isolationsstufe, da sie von anderen Transaktionen platzierte Sperren ignoriert.READ UNCOMMITTED is the least restrictive isolation level because it ignores locks placed by other transactions. Mit READ UNCOMMITTED ausgeführte Transaktionen können geänderte Datenwerte lesen, die noch nicht von anderen Transaktionen gespeichert wurden; diese werden "unsaubere" Lesevorgänge genannt.Transactions executing under READ UNCOMMITTED can read modified data values that have not yet been committed by other transactions; these are called "dirty" reads.

  • READ COMMITTED ist die Standardisolationsstufe für SQL Server.READ COMMITTED is the default isolation level for SQL Server. Er verhindert "unsaubere" Lesevorgänge, indem festgelegt wird, dass Anweisungen keine Datenwerte lesen können, die geändert, aber noch nicht von anderen Transaktionen gespeichert wurden.It prevents dirty reads by specifying that statements cannot read data values that have been modified but not yet committed by other transactions. Andere Transaktionen können immer noch Daten zwischen Ausführungen einzelner Anweisungen innerhalb der aktuellen Transaktion ändern, einfügen oder löschen, was zu nicht wiederholbaren Lesevorgängen oder "Phantomdaten" führt.Other transactions can still modify, insert, or delete data between executions of individual statements within the current transaction, resulting in non-repeatable reads, or "phantom" data.

  • REPEATABLE READ ist eine restriktivere Isolationsstufe als READ COMMITTED.REPEATABLE READ is a more restrictive isolation level than READ COMMITTED. Er umfasst READ COMMITTED und gibt zusätzlich an, dass keine andere Transaktion Daten ändern oder löschen kann, die von der aktuellen Transaktion gelesen wurden, bis die aktuelle Transaktion einen Commit durchführt.It encompasses READ COMMITTED and additionally specifies that no other transactions can modify or delete data that has been read by the current transaction until the current transaction commits. Die Parallelität ist geringer als bei READ COMMITTED, da gemeinsam verwendete Sperren für gelesene Daten für die Dauer der Transaktion beibehalten und nicht am Ende jeder Anweisung zurückgegeben werden.Concurrency is lower than for READ COMMITTED because shared locks on read data are held for the duration of the transaction instead of being released at the end of each statement.

  • SERIALIZABLE ist die restriktivste Isolationsstufe, da sie bis zum Abschluss der Transaktion vollständige Schlüsselbereiche sperrt und die Sperren beibehält.SERIALIZABLE is the most restrictive isolation level, because it locks entire ranges of keys and holds the locks until the transaction is complete. Er umfasst REPEATABLE READ und fügt die Einschränkung hinzu, dass andere Transaktionen bis zum Abschluss der Transaktion keine neuen Zeilen in Bereiche einfügen können, die von der Transaktion gelesen wurden.It encompasses REPEATABLE READ and adds the restriction that other transactions cannot insert new rows into ranges that have been read by the transaction until the transaction is complete.

Weitere Informationen finden Sie in der Onlinedokumentation zu SQL Server unter "Isolation Levels".For more information, see "Isolation Levels" in SQL Server Books Online.

Snapshot-IsolationsstufenerweiterungenSnapshot Isolation Level Extensions

In SQL Server wurden mit der SNAPSHOT-Isolationsstufe und einer zusätzlichen READ COMMITTED-Implementierung Erweiterungen zu den SQL-92-Isolationsstufen eingeführt.SQL Server introduced extensions to the SQL-92 isolation levels with the introduction of the SNAPSHOT isolation level and an additional implementation of READ COMMITTED. Die READ_COMMITTED_SNAPSHOT-Isolationsstufe kann READ COMMITTED für alle Transaktionen auf transparente Weise ersetzen.The READ_COMMITTED_SNAPSHOT isolation level can transparently replace READ COMMITTED for all transactions.

  • SNAPSHOT-Isolation gibt an, dass innerhalb einer Transaktion gelesene Daten niemals Änderungen widerspiegeln, die von anderen gleichzeitigen Transaktionen durchgeführt wurden.SNAPSHOT isolation specifies that data read within a transaction will never reflect changes made by other simultaneous transactions. Die Transaktion verwendet die Datenzeilenversionen, die zu Beginn der Transaktion vorhanden sind.The transaction uses the data row versions that exist when the transaction begins. Beim Lesen der Daten werden keine Sperren erstellt, deshalb blockieren SNAPSHOT-Transaktionen das Schreiben von Daten durch andere Transaktionen nicht.No locks are placed on the data when it is read, so SNAPSHOT transactions do not block other transactions from writing data. Transaktionen, die Daten schreiben, blockieren das Lesen von Daten durch andere Transaktionen nicht.Transactions that write data do not block snapshot transactions from reading data. Um die Snapshot-Isolation verwenden zu können, müssen Sie die ALLOW_SNAPSHOT_ISOLATION-Datenbankoption aktivieren.You need to enable snapshot isolation by setting the ALLOW_SNAPSHOT_ISOLATION database option in order to use it.

  • Die READ_COMMITTED_SNAPSHOT-Datenbankoption bestimmt das Verhalten der READ COMMITTED-Standardisolationsstufe, wenn Snapshot-Isolation in einer Datenbank aktiviert ist.The READ_COMMITTED_SNAPSHOT database option determines the behavior of the default READ COMMITTED isolation level when snapshot isolation is enabled in a database. Wenn Sie READ_COMMITTED_SNAPSHOT ON nicht explizit angeben, wird READ COMMITTED für alle impliziten Transaktionen angewendet.If you do not explicitly specify READ_COMMITTED_SNAPSHOT ON, READ COMMITTED is applied to all implicit transactions. Dies führt zum gleichen Verhalten wie beim Festlegen von READ_COMMITTED_SNAPSHOT auf OFF (Standardeinstellung).This produces the same behavior as setting READ_COMMITTED_SNAPSHOT OFF (the default). Wenn READ_COMMITTED_SNAPSHOT auf OFF festgelegt ist, verwendet das Datenbankmodul gemeinsame Sperren, um die Standardisolationsstufe zu erzwingen.When READ_COMMITTED_SNAPSHOT OFF is in effect, the Database Engine uses shared locks to enforce the default isolation level. Wenn Sie die READ_COMMITTED_SNAPSHOT-Datenbankoption auf ON festlegen, verwendet das Datenbankmodul Zeilenversionserstellung und die Snapshot-Isolation als Standard, anstatt Sperren zum Schutz der Daten zu verwenden.If you set the READ_COMMITTED_SNAPSHOT database option to ON, the database engine uses row versioning and snapshot isolation as the default, instead of using locks to protect the data.

Funktionsweise der Snapshot-Isolation und der ZeilenversionserstellungHow Snapshot Isolation and Row Versioning Work

Wenn die SNAPSHOT-Isolationsstufe jedes Mal aktiviert ist, eine Zeile aktualisiert wird, speichert das SQL Server-Datenbankmodul eine Kopie der Ursprungszeile in Tempdb, und fügt die Zeile eine Transaktionsfolgenummer hinzu.When the SNAPSHOT isolation level is enabled, each time a row is updated, the SQL Server Database Engine stores a copy of the original row in tempdb, and adds a transaction sequence number to the row. Nachfolgend ist die Reihenfolge der Ereignisse angegeben:The following is the sequence of events that occurs:

  • Eine neue Transaktion wird initiiert, und ihr wird eine Transaktionsfolgenummer zugewiesen.A new transaction is initiated, and it is assigned a transaction sequence number.

  • Das Datenbankmodul liest eine Zeile innerhalb der Transaktion und ruft die Zeilenversion von Tempdb , deren Sequenznummer ist, kleiner ist als die Transaktionsfolgenummer und am nächsten.The Database Engine reads a row within the transaction and retrieves the row version from tempdb whose sequence number is closest to, and lower than, the transaction sequence number.

  • Das Datenbankmodul prüft, ob die Transaktionsfolgenummer in der Liste von Transaktionsfolgenummern der nicht übernommenen Transaktionen vorhanden ist, die beim Start der Snapshot-Transaktion aktiv waren.The Database Engine checks to see if the transaction sequence number is not in the list of transaction sequence numbers of the uncommitted transactions active when the snapshot transaction started.

  • Die Transaktion liest die Version der Zeile aus Tempdb war beim Start der Transaktion aktuell war.The transaction reads the version of the row from tempdb that was current as of the start of the transaction. Nach dem Start der Transaktion kann diese keine neu eingefügten Zeilen erfassen, da diese Folgenummernwerte höher sind als der Wert der Transaktionsfolgenummer.It will not see new rows inserted after the transaction was started because those sequence number values will be higher than the value of the transaction sequence number.

  • Die aktuelle Transaktion sehen die Zeilen, die nach dem Beginn der Transaktion gelöscht wurden, weil eine Zeilenversion in Tempdb mit einer niedrigeren Sequenzwert.The current transaction will see rows that were deleted after the transaction began, because there will be a row version in tempdb with a lower sequence number value.

Das Ergebnis der Snapshot-Isolation besteht darin, dass die Transaktion alle Daten so erfasst, wie sie zum Transaktionsstart vorhanden waren, ohne für die zugrunde liegenden Tabellen Sperren umzusetzen oder zu platzieren.The net effect of snapshot isolation is that the transaction sees all of the data as it existed at the start of the transaction, without honoring or placing any locks on the underlying tables. Dies kann in Situationen mit Konflikten zu einer Leistungssteigerung führen.This can result in performance improvements in situations where there is contention.

Eine Snapshot-Transaktion verwendet immer vollständige Parallelitätssteuerung, wobei alle Sperren zurückgehalten werden, die das Aktualisieren von Zeilen durch andere Transaktionen verhindern.A snapshot transaction always uses optimistic concurrency control, withholding any locks that would prevent other transactions from updating rows. Wenn eine Snapshot-Transaktion versucht, ein Update für eine Zeile zu übernehmen, die nach dem Beginn der Transaktion geändert wurde, wird die Transaktion zurückgenommen und ein Fehler ausgelöst.If a snapshot transaction attempts to commit an update to a row that was changed after the transaction began, the transaction is rolled back, and an error is raised.

Verwenden der Snapshot-Isolation in ADO.NETWorking with Snapshot Isolation in ADO.NET

Die Snapshot-Isolation wird in ADO.NET durch die SqlTransaction-Klasse unterstützt.Snapshot isolation is supported in ADO.NET by the SqlTransaction class. Wenn eine Datenbank wurde für die Snapshot-Isolation aktiviert, aber nicht für READ_COMMITTED_SNAPSHOT ON konfiguriert ist, müssen Sie Initiieren einer SqlTransaction mithilfe der IsolationLevel.Snapshot Enumerationswert beim Aufrufen der BeginTransaction Methode.If a database has been enabled for snapshot isolation but is not configured for READ_COMMITTED_SNAPSHOT ON, you must initiate a SqlTransaction using the IsolationLevel.Snapshot enumeration value when calling the BeginTransaction method. Für dieses Codefragment wird angenommen, dass es sich bei der Verbindung um ein offenes SqlConnection-Objekt handelt.This code fragment assumes that connection is an open SqlConnection object.

Dim sqlTran As SqlTransaction = _  
  connection.BeginTransaction(IsolationLevel.Snapshot)  
SqlTransaction sqlTran =   
  connection.BeginTransaction(IsolationLevel.Snapshot);  

BeispielExample

Im folgenden Beispiel wird gezeigt, wie sich die verschiedenen Isolationsstufen beim Zugriff auf gesperrte Daten verhalten. Dieses Beispiel ist nicht zur Verwendung in Produktionscode bestimmt.The following example demonstrates how the different isolation levels behave by attempting to access locked data, and it is not intended to be used in production code.

Der Code eine Verbindung mit der AdventureWorks -Beispieldatenbank in SQL Server und erstellt eine Tabelle namens TestSnapshot und fügt eine Zeile mit Daten.The code connects to the AdventureWorks sample database in SQL Server and creates a table named TestSnapshot and inserts one row of data. Der Code verwendet die ALTER DATABASE Transact-SQL-Anweisung zum Aktivieren der Snapshot-Isolation für die Datenbank, legt aber nicht die READ_COMMITTED_SNAPSHOT-Option fest, wodurch das READ COMMITTED-Isolationsstufenverhalten bestehen bleibt.The code uses the ALTER DATABASE Transact-SQL statement to turn on snapshot isolation for the database, but it does not set the READ_COMMITTED_SNAPSHOT option, leaving the default READ COMMITTED isolation-level behavior in effect. Der Code führt dann die folgenden Aktionen aus:The code then performs the following actions:

  • Er startet sqlTransaction1, die die SERIALIZABLE-Isolationsstufe verwendet, um eine Updatetransaktion zu starten. sqlTransaction1 wird allerdings nicht fertig gestellt.It begins, but does not complete, sqlTransaction1, which uses the SERIALIZABLE isolation level to start an update transaction. Dadurch wird die Tabelle gesperrt.This has the effect of locking the table.

  • Der Code öffnet eine zweite Verbindung und initiiert eine zweite Transaktion mit SNAPSHOT-Isolationsstufe zum Lesen der Daten in der TestSnapshot Tabelle.It opens a second connection and initiates a second transaction using the SNAPSHOT isolation level to read the data in the TestSnapshot table. Da die Snapshot-Isolation aktiviert ist, kann diese Transaktion die Daten lesen, die vor dem Start von sqlTransaction1 vorhanden waren.Because snapshot isolation is enabled, this transaction can read the data that existed before sqlTransaction1 started.

  • Der Code öffnet eine dritte Verbindung und initiiert eine Transaktion mit der READ COMMITED-Isolationsstufe, um die Daten in der Tabelle zu lesen.It opens a third connection and initiates a transaction using the READ COMMITTED isolation level to attempt to read the data in the table. In diesem Fall kann der Code die Daten nicht lesen, weil er nicht über die Sperren hinweg lesen kann, die in der ersten Transaktion für die Tabelle platziert wurden, und löst eine Zeitüberschreitung aus. Das gleiche Ergebnis tritt auch bei den Isolationsstufen REPEATABLE READ und SERIALIZABLE auf, weil diese Isolationsstufen ebenfalls nicht über die in der ersten Transaktion platzierten Sperren hinweg lesen können.In this case, the code cannot read the data because it cannot read past the locks placed on the table in the first transaction and times out. The same result would occur if the REPEATABLE READ and SERIALIZABLE isolation levels were used because these isolation levels also cannot read past the locks placed in the first transaction.

  • Der Code öffnet eine vierte Verbindung und initiiert mit der READ UNCOMMITTED-Isolationsstufe eine Transaktion, die einen "unsauberen" Lesevorgang für den nicht übernommenen Wert in sqlTransaction1 durchführt.It opens a fourth connection and initiates a transaction using the READ UNCOMMITTED isolation level, which performs a dirty read of the uncommitted value in sqlTransaction1. Dieser Wert ist möglicherweise tatsächlich nie in der Datenbank vorhanden, wenn die erste Transaktion nicht übernommen wird.This value may never actually exist in the database if the first transaction is not committed.

  • Er führt einen Rollback für die erste Transaktion und Bereinigung durch, indem die TestSnapshot Tabelle, und schalten die snapshot-Isolation für die AdventureWorks Datenbank.It rolls back the first transaction and cleans up by deleting the TestSnapshot table and turning off snapshot isolation for the AdventureWorks database.

Hinweis

In den folgenden Beispielen wird dieselbe Verbindungszeichenfolge verwendet, wobei aber das Verbindungspooling deaktiviert ist.The following examples use the same connection string with connection pooling turned off. Wenn sich eine Verbindung in einem Pool befindet, führt die Rücksetzung ihrer Isolationsstufe nicht automatisch auch zur Rücksetzung der Isolationsstufe auf dem Server.If a connection is pooled, resetting its isolation level does not reset the isolation level at the server. Nachfolgende Verbindungen, die dieselbe innere Verbindung aus dem Pool verwenden, beginnen daher mit der Isolationsstufe, die für die Verbindung im Pool festgelegt ist.As a result, subsequent connections that use the same pooled inner connection start with their isolation levels set to that of the pooled connection. Alternativ zum Deaktivieren des Verbindungspoolings können Sie auch die Isolationsstufe explizit für jede Verbindung festlegen.An alternative to turning off connection pooling is to set the isolation level explicitly for each connection.

// Assumes GetConnectionString returns a valid connection string
// where pooling is turned off by setting Pooling=False;. 
string connectionString = GetConnectionString();
using (SqlConnection connection1 = new SqlConnection(connectionString))
{
    // Drop the TestSnapshot table if it exists
    connection1.Open();
    SqlCommand command1 = connection1.CreateCommand();
    command1.CommandText = "IF EXISTS "
        + "(SELECT * FROM sys.tables WHERE name=N'TestSnapshot') "
        + "DROP TABLE TestSnapshot";
    try
    {
        command1.ExecuteNonQuery();
    }
    catch (Exception ex)
    {
        Console.WriteLine(ex.Message);
    }
    // Enable Snapshot isolation
    command1.CommandText =
        "ALTER DATABASE AdventureWorks SET ALLOW_SNAPSHOT_ISOLATION ON";
    command1.ExecuteNonQuery();

    // Create a table named TestSnapshot and insert one row of data
    command1.CommandText =
        "CREATE TABLE TestSnapshot (ID int primary key, valueCol int)";
    command1.ExecuteNonQuery();
    command1.CommandText =
        "INSERT INTO TestSnapshot VALUES (1,1)";
    command1.ExecuteNonQuery();

    // Begin, but do not complete, a transaction to update the data 
    // with the Serializable isolation level, which locks the table
    // pending the commit or rollback of the update. The original 
    // value in valueCol was 1, the proposed new value is 22.
    SqlTransaction transaction1 =
        connection1.BeginTransaction(IsolationLevel.Serializable);
    command1.Transaction = transaction1;
    command1.CommandText =
        "UPDATE TestSnapshot SET valueCol=22 WHERE ID=1";
    command1.ExecuteNonQuery();

    // Open a second connection to AdventureWorks
    using (SqlConnection connection2 = new SqlConnection(connectionString))
    {
        connection2.Open();
        // Initiate a second transaction to read from TestSnapshot
        // using Snapshot isolation. This will read the original 
        // value of 1 since transaction1 has not yet committed.
        SqlCommand command2 = connection2.CreateCommand();
        SqlTransaction transaction2 =
            connection2.BeginTransaction(IsolationLevel.Snapshot);
        command2.Transaction = transaction2;
        command2.CommandText =
            "SELECT ID, valueCol FROM TestSnapshot";
        SqlDataReader reader2 = command2.ExecuteReader();
        while (reader2.Read())
        {
            Console.WriteLine("Expected 1,1 Actual "
                + reader2.GetValue(0).ToString()
                + "," + reader2.GetValue(1).ToString());
        }
        transaction2.Commit();
    }

    // Open a third connection to AdventureWorks and
    // initiate a third transaction to read from TestSnapshot
    // using ReadCommitted isolation level. This transaction
    // will not be able to view the data because of 
    // the locks placed on the table in transaction1
    // and will time out after 4 seconds.
    // You would see the same behavior with the
    // RepeatableRead or Serializable isolation levels.
    using (SqlConnection connection3 = new SqlConnection(connectionString))
    {
        connection3.Open();
        SqlCommand command3 = connection3.CreateCommand();
        SqlTransaction transaction3 =
            connection3.BeginTransaction(IsolationLevel.ReadCommitted);
        command3.Transaction = transaction3;
        command3.CommandText =
            "SELECT ID, valueCol FROM TestSnapshot";
        command3.CommandTimeout = 4;
        try
        {
            SqlDataReader sqldatareader3 = command3.ExecuteReader();
            while (sqldatareader3.Read())
            {
                Console.WriteLine("You should never hit this.");
            }
            transaction3.Commit();
        }
        catch (Exception ex)
        {
            Console.WriteLine("Expected timeout expired exception: "
                + ex.Message);
            transaction3.Rollback();
        }
    }

    // Open a fourth connection to AdventureWorks and
    // initiate a fourth transaction to read from TestSnapshot
    // using the ReadUncommitted isolation level. ReadUncommitted
    // will not hit the table lock, and will allow a dirty read  
    // of the proposed new value 22 for valueCol. If the first
    // transaction rolls back, this value will never actually have
    // existed in the database.
    using (SqlConnection connection4 = new SqlConnection(connectionString))
    {
        connection4.Open();
        SqlCommand command4 = connection4.CreateCommand();
        SqlTransaction transaction4 =
            connection4.BeginTransaction(IsolationLevel.ReadUncommitted);
        command4.Transaction = transaction4;
        command4.CommandText =
            "SELECT ID, valueCol FROM TestSnapshot";
        SqlDataReader reader4 = command4.ExecuteReader();
        while (reader4.Read())
        {
            Console.WriteLine("Expected 1,22 Actual "
                + reader4.GetValue(0).ToString()
                + "," + reader4.GetValue(1).ToString());
        }

        transaction4.Commit();
    }

    // Roll back the first transaction
    transaction1.Rollback();
}

// CLEANUP
// Delete the TestSnapshot table and set
// ALLOW_SNAPSHOT_ISOLATION OFF
using (SqlConnection connection5 = new SqlConnection(connectionString))
{
    connection5.Open();
    SqlCommand command5 = connection5.CreateCommand();
    command5.CommandText = "DROP TABLE TestSnapshot";
    SqlCommand command6 = connection5.CreateCommand();
    command6.CommandText =
        "ALTER DATABASE AdventureWorks SET ALLOW_SNAPSHOT_ISOLATION OFF";
    try
    {
        command5.ExecuteNonQuery();
        command6.ExecuteNonQuery();
    }
    catch (Exception ex)
    {
        Console.WriteLine(ex.Message);
    }
}
Console.WriteLine("Done!");
' Assumes GetConnectionString returns a valid connection string
' where pooling is turned off by setting Pooling=False;. 
Dim connectionString As String = GetConnectionString()

Using connection1 As New SqlConnection(connectionString)
    ' Drop the TestSnapshot table if it exists
    connection1.Open()
    Dim command1 As SqlCommand = connection1.CreateCommand
    command1.CommandText = "IF EXISTS " & _
    "(SELECT * FROM sys.tables WHERE name=N'TestSnapshot') " _
      & "DROP TABLE TestSnapshot"
    Try
        command1.ExecuteNonQuery()
    Catch ex As Exception
        Console.WriteLine(ex.Message)
    End Try

    ' Enable SNAPSHOT isolation 
    command1.CommandText = _
    "ALTER DATABASE AdventureWorks SET ALLOW_SNAPSHOT_ISOLATION ON"
    command1.ExecuteNonQuery()

    ' Create a table named TestSnapshot and insert one row of data
    command1.CommandText = _
    "CREATE TABLE TestSnapshot (ID int primary key, valueCol int)"
    command1.ExecuteNonQuery()
    command1.CommandText = _
      "INSERT INTO TestSnapshot VALUES (1,1)"
    command1.ExecuteNonQuery()

    ' Begin, but do not complete, a transaction to update the data 
    ' with the Serializable isolation level, which locks the table
    ' pending the commit or rollback of the update. The original 
    ' value in valueCol was 1, the proposed new value is 22.
    Dim transaction1 As SqlTransaction = _
      connection1.BeginTransaction(IsolationLevel.Serializable)
    command1.Transaction = transaction1
    command1.CommandText = _
     "UPDATE TestSnapshot SET valueCol=22 WHERE ID=1"
    command1.ExecuteNonQuery()

    ' Open a second connection to AdventureWorks
    Dim connection2 As SqlConnection = New SqlConnection(connectionString)
    Using connection2
        connection2.Open()

        ' Initiate a second transaction to read from TestSnapshot
        ' using Snapshot isolation. This will read the original 
        ' value of 1 since transaction1 has not yet committed.
        Dim command2 As SqlCommand = connection2.CreateCommand()
        Dim transaction2 As SqlTransaction = _
          connection2.BeginTransaction(IsolationLevel.Snapshot)
        command2.Transaction = transaction2
        command2.CommandText = _
            "SELECT ID, valueCol FROM TestSnapshot"
        Dim reader2 As SqlDataReader = _
            command2.ExecuteReader()
        While reader2.Read()
            Console.WriteLine("Expected 1,1 Actual " _
              & reader2.GetValue(0).ToString() + "," _
              & reader2.GetValue(1).ToString())
        End While
        transaction2.Commit()
    End Using

    ' Open a third connection to AdventureWorks and
    ' initiate a third transaction to read from TestSnapshot
    ' using the ReadCommitted isolation level. This transaction
    ' will not be able to view the data because of 
    ' the locks placed on the table in transaction1
    ' and will time out after 4 seconds.
    ' You would see the same behavior with the
    ' RepeatableRead or Serializable isolation levels.
    Dim connection3 As SqlConnection = New SqlConnection(connectionString)
    Using connection3
        connection3.Open()
        Dim command3 As SqlCommand = connection3.CreateCommand()
        Dim transaction3 As SqlTransaction = _
            connection3.BeginTransaction(IsolationLevel.ReadCommitted)
        command3.Transaction = transaction3
        command3.CommandText = _
            "SELECT ID, valueCol FROM TestSnapshot"
        command3.CommandTimeout = 4

        Try
            Dim reader3 As SqlDataReader = command3.ExecuteReader()
            While reader3.Read()
                Console.WriteLine("You should never hit this.")
            End While
            transaction3.Commit()
        Catch ex As Exception
            Console.WriteLine("Expected timeout expired exception: " _
              & ex.Message)
            transaction3.Rollback()
        End Try
    End Using

    ' Open a fourth connection to AdventureWorks and
    ' initiate a fourth transaction to read from TestSnapshot
    ' using the ReadUncommitted isolation level. ReadUncommitted
    ' will not hit the table lock, and will allow a dirty read  
    ' of the proposed new value 22. If the first transaction 
    ' transaction rolls back, this value will never actually have
    ' existed in the database.
    Dim connection4 As SqlConnection = New SqlConnection(connectionString)
    Using connection4
        connection4.Open()
        Dim command4 As SqlCommand = connection4.CreateCommand()
        Dim transaction4 As SqlTransaction = _
          connection4.BeginTransaction(IsolationLevel.ReadUncommitted)
        command4.Transaction = transaction4
        command4.CommandText = _
            "SELECT ID, valueCol FROM TestSnapshot"
        Dim reader4 As SqlDataReader = _
            command4.ExecuteReader()
        While reader4.Read()
            Console.WriteLine("Expected 1,22 Actual " _
              & reader4.GetValue(0).ToString() _
              & "," + reader4.GetValue(1).ToString())
        End While
        transaction4.Commit()

        ' Rollback transaction1
        transaction1.Rollback()
    End Using
End Using

' CLEANUP
' Drop TestSnapshot table and set
' ALLOW_SNAPSHOT_ISOLATION OFF for AdventureWorks
Dim connection5 As New SqlConnection(connectionString)
Using connection5
    connection5.Open()
    Dim command5 As SqlCommand = connection5.CreateCommand()
    command5.CommandText = "DROP TABLE TestSnapshot"
    Dim command6 As SqlCommand = connection5.CreateCommand()
    command6.CommandText = _
   "ALTER DATABASE AdventureWorks SET ALLOW_SNAPSHOT_ISOLATION OFF"
    Try
        command5.ExecuteNonQuery()
        command6.ExecuteNonQuery()
    Catch ex As Exception
        Console.WriteLine(ex.Message)
    End Try
End Using

BeispielExample

Im folgenden Beispiel wird das Verhalten der Snapshot-Isolation beim Ändern von Daten gezeigt.The following example demonstrates the behavior of snapshot isolation when data is being modified. Der Code führt die folgenden Aktionen aus:The code performs the following actions:

  • Eine Verbindung mit der AdventureWorks Beispiel her und aktiviert die SNAPSHOT-Isolation.Connects to the AdventureWorks sample database and enables SNAPSHOT isolation.

  • Erstellt eine Tabelle namens TestSnapshotUpdate und fügt drei Zeilen mit Beispieldaten.Creates a table named TestSnapshotUpdate and inserts three rows of sample data.

  • Startet sqlTransaction1 mit einer SNAPSHOT-Isolation, stellt diese aber nicht fertig.Begins, but does not complete, sqlTransaction1 using SNAPSHOT isolation. In der Transaktion werden drei Zeilen mit Daten ausgewählt.Three rows of data are selected in the transaction.

  • Erstellt eine zweite SqlConnection auf AdventureWorks und erstellt eine zweite Transaktion mit der READ COMMITTED-Isolationsstufe, die einen Wert in einer der in sqlTransaction1 ausgewählten Zeilen aktualisiert.Creates a second SqlConnection to AdventureWorks and creates a second transaction using the READ COMMITTED isolation level that updates a value in one of the rows selected in sqlTransaction1.

  • Führt einen Commit für sqlTransaction2 durch.Commits sqlTransaction2.

  • Kehrt zu sqlTransaction1 zurück und versucht, dieselbe Zeile zu aktualisieren, für die sqlTransaction1 bereits einen Commit durchgeführt hat.Returns to sqlTransaction1 and attempts to update the same row that sqlTransaction1 already committed. Der Fehler 3960 wird ausgelöst, und sqlTransaction1 wird automatisch zurückgenommen.Error 3960 is raised, and sqlTransaction1 is rolled back automatically. Die SqlException.Number und SqlException.Message werden im Konsolenfenster angezeigt.The SqlException.Number and SqlException.Message are displayed in the Console window.

  • Führt Bereinigungscode zum Deaktivieren der Snapshot-Isolation in AdventureWorks und löschen Sie die TestSnapshotUpdate Tabelle.Executes clean-up code to turn off snapshot isolation in AdventureWorks and delete the TestSnapshotUpdate table.

// Assumes GetConnectionString returns a valid connection string
// where pooling is turned off by setting Pooling=False;. 
string connectionString = GetConnectionString();
using (SqlConnection connection1 = new SqlConnection(connectionString))
{
    connection1.Open();
    SqlCommand command1 = connection1.CreateCommand();

    // Enable Snapshot isolation in AdventureWorks
    command1.CommandText =
        "ALTER DATABASE AdventureWorks SET ALLOW_SNAPSHOT_ISOLATION ON";
    try
    {
        command1.ExecuteNonQuery();
        Console.WriteLine(
            "Snapshot Isolation turned on in AdventureWorks.");
    }
    catch (Exception ex)
    {
        Console.WriteLine("ALLOW_SNAPSHOT_ISOLATION ON failed: {0}", ex.Message);
    }
    // Create a table 
    command1.CommandText =
        "IF EXISTS "
        + "(SELECT * FROM sys.tables "
        + "WHERE name=N'TestSnapshotUpdate')"
        + " DROP TABLE TestSnapshotUpdate";
    command1.ExecuteNonQuery();
    command1.CommandText =
        "CREATE TABLE TestSnapshotUpdate "
        + "(ID int primary key, CharCol nvarchar(100));";
    try
    {
        command1.ExecuteNonQuery();
        Console.WriteLine("TestSnapshotUpdate table created.");
    }
    catch (Exception ex)
    {
        Console.WriteLine("CREATE TABLE failed: {0}", ex.Message);
    }
    // Insert some data
    command1.CommandText =
        "INSERT INTO TestSnapshotUpdate VALUES (1,N'abcdefg');"
        + "INSERT INTO TestSnapshotUpdate VALUES (2,N'hijklmn');"
        + "INSERT INTO TestSnapshotUpdate VALUES (3,N'opqrstuv');";
    try
    {
        command1.ExecuteNonQuery();
        Console.WriteLine("Data inserted TestSnapshotUpdate table.");
    }
    catch (Exception ex)
    {
        Console.WriteLine(ex.Message);
    }

    // Begin, but do not complete, a transaction 
    // using the Snapshot isolation level.
    SqlTransaction transaction1 = null;
    try
    {
        transaction1 = connection1.BeginTransaction(IsolationLevel.Snapshot);
        command1.CommandText =
            "SELECT * FROM TestSnapshotUpdate WHERE ID BETWEEN 1 AND 3";
        command1.Transaction = transaction1;
        command1.ExecuteNonQuery();
        Console.WriteLine("Snapshot transaction1 started.");

        // Open a second Connection/Transaction to update data
        // using ReadCommitted. This transaction should succeed.
        using (SqlConnection connection2 = new SqlConnection(connectionString))
        {
            connection2.Open();
            SqlCommand command2 = connection2.CreateCommand();
            command2.CommandText = "UPDATE TestSnapshotUpdate SET CharCol="
                + "N'New value from Connection2' WHERE ID=1";
            SqlTransaction transaction2 =
                connection2.BeginTransaction(IsolationLevel.ReadCommitted);
            command2.Transaction = transaction2;
            try
            {
                command2.ExecuteNonQuery();
                transaction2.Commit();
                Console.WriteLine(
                    "transaction2 has modified data and committed.");
            }
            catch (SqlException ex)
            {
                Console.WriteLine(ex.Message);
                transaction2.Rollback();
            }
            finally
            {
                transaction2.Dispose();
            }
        }

        // Now try to update a row in Connection1/Transaction1.
        // This transaction should fail because Transaction2
        // succeeded in modifying the data.
        command1.CommandText =
            "UPDATE TestSnapshotUpdate SET CharCol="
            + "N'New value from Connection1' WHERE ID=1";
        command1.Transaction = transaction1;
        command1.ExecuteNonQuery();
        transaction1.Commit();
        Console.WriteLine("You should never see this.");
    }
    catch (SqlException ex)
    {
        Console.WriteLine("Expected failure for transaction1:");
        Console.WriteLine("  {0}: {1}", ex.Number, ex.Message);
    }
    finally
    {
        transaction1.Dispose();
    }
}

// CLEANUP:
// Turn off Snapshot isolation and delete the table
using (SqlConnection connection3 = new SqlConnection(connectionString))
{
    connection3.Open();
    SqlCommand command3 = connection3.CreateCommand();
    command3.CommandText =
        "ALTER DATABASE AdventureWorks SET ALLOW_SNAPSHOT_ISOLATION OFF";
    try
    {
        command3.ExecuteNonQuery();
        Console.WriteLine(
            "CLEANUP: Snapshot isolation turned off in AdventureWorks.");
    }
    catch (Exception ex)
    {
        Console.WriteLine("CLEANUP FAILED: {0}", ex.Message);
    }
    command3.CommandText = "DROP TABLE TestSnapshotUpdate";
    try
    {
        command3.ExecuteNonQuery();
        Console.WriteLine("CLEANUP: TestSnapshotUpdate table deleted.");
    }
    catch (Exception ex)
    {
        Console.WriteLine("CLEANUP FAILED: {0}", ex.Message);
    }
}
' Assumes GetConnectionString returns a valid connection string
' where pooling is turned off by setting Pooling=False;. 
Dim connectionString As String = GetConnectionString()

Using connection1 As New SqlConnection(connectionString)
    ' Enable Snapshot isolation in AdventureWorks
    connection1.Open()
    Dim command1 As SqlCommand = connection1.CreateCommand
    command1.CommandText = _
   "ALTER DATABASE AdventureWorks SET ALLOW_SNAPSHOT_ISOLATION ON;"
    Try
        command1.ExecuteNonQuery()
        Console.WriteLine( _
         "Snapshot Isolation turned on in AdventureWorks.")
    Catch ex As Exception
        Console.WriteLine("ALLOW_SNAPSHOT_ISOLATION failed: {0}", ex.Message)
    End Try

    ' Create a table
    command1.CommandText = _
      "IF EXISTS (SELECT * FROM sys.databases " _
      & "WHERE name=N'TestSnapshotUpdate') " _
      & "DROP TABLE TestSnapshotUpdate"
    command1.ExecuteNonQuery()
    command1.CommandText = _
      "CREATE TABLE TestSnapshotUpdate (ID int primary key, " _
      & "CharCol nvarchar(100));"
    Try
        command1.ExecuteNonQuery()
        Console.WriteLine("TestSnapshotUpdate table created.")
    Catch ex As Exception
        Console.WriteLine("CREATE TABLE failed: {0}", ex.Message)
    End Try

    ' Insert some data
    command1.CommandText = _
      "INSERT INTO TestSnapshotUpdate VALUES (1,N'abcdefg');" _
      & "INSERT INTO TestSnapshotUpdate VALUES (2,N'hijklmn');" _
      & "INSERT INTO TestSnapshotUpdate VALUES (3,N'opqrstuv');"
    Try
        command1.ExecuteNonQuery()
        Console.WriteLine("Data inserted TestSnapshotUpdate table.")
    Catch ex As Exception
        Console.WriteLine(ex.Message)
    End Try

    ' Begin, but do not complete, a transaction
    ' using the Snapshot isolation level
    Dim transaction1 As SqlTransaction = Nothing
    Try
        transaction1 = connection1.BeginTransaction(IsolationLevel.Snapshot)
        command1.CommandText = _
          "SELECT * FROM TestSnapshotUpdate WHERE ID " _
          & "BETWEEN 1 AND 3"
        command1.Transaction = transaction1
        command1.ExecuteNonQuery()
        Console.WriteLine("Snapshot transaction1 started.")

        ' Open a second Connection/Transaction to update data
        ' using ReadCommitted. This transaction should succeed.
        Dim connection2 As SqlConnection = New SqlConnection(connectionString)
        Using connection2
            connection2.Open()
            Dim command2 As SqlCommand = connection2.CreateCommand()
            command2.CommandText = "UPDATE TestSnapshotUpdate SET " _
              & "CharCol=N'New value from Connection2' WHERE ID=1"
            Dim transaction2 As SqlTransaction = _
              connection2.BeginTransaction(IsolationLevel.ReadCommitted)
            command2.Transaction = transaction2
            Try
                command2.ExecuteNonQuery()
                transaction2.Commit()
                Console.WriteLine( _
                  "transaction2 has modified data and committed.")
            Catch ex As SqlException
                Console.WriteLine(ex.Message)
                transaction2.Rollback()
            Finally
                transaction2.Dispose()
            End Try
        End Using

        ' Now try to update a row in Connection1/Transaction1.
        ' This transaction should fail because Transaction2
        ' succeeded in modifying the data.
        command1.CommandText = _
          "UPDATE TestSnapshotUpdate SET CharCol=" _
            & "N'New value from Connection1' WHERE ID=1"
        command1.Transaction = transaction1
        command1.ExecuteNonQuery()
        transaction1.Commit()
        Console.WriteLine("You should never see this.")

    Catch ex As SqlException
        Console.WriteLine("Expected failure for transaction1:")
        Console.WriteLine("  {0}: {1}", ex.Number, ex.Message)
    Finally
        transaction1.Dispose()
    End Try
End Using

' CLEANUP:
' Turn off Snapshot isolation and delete the table
Dim connection3 As New SqlConnection(connectionString)
Using connection3
    connection3.Open()
    Dim command3 As SqlCommand = connection3.CreateCommand()
    command3.CommandText = _
  "ALTER DATABASE AdventureWorks SET ALLOW_SNAPSHOT_ISOLATION OFF"
    Try
        command3.ExecuteNonQuery()
        Console.WriteLine( _
         "Snapshot isolation turned off in AdventureWorks.")
    Catch ex As Exception
        Console.WriteLine("CLEANUP FAILED: {0}", ex.Message)
    End Try

    command3.CommandText = "DROP TABLE TestSnapshotUpdate"
    Try
        command3.ExecuteNonQuery()
        Console.WriteLine("TestSnapshotUpdate table deleted.")
    Catch ex As Exception
        Console.WriteLine("CLEANUP FAILED: {0}", ex.Message)
    End Try
End Using

Verwenden von Sperrhinweisen mit der Snapshot-IsolationUsing Lock Hints with Snapshot Isolation

Im vorigen Beispiel wählt die erste Transaktion Daten aus, und eine zweite Transaktion aktualisiert die Daten, bevor die erste Transaktion beendet werden kann, wodurch ein Updatekonflikt entsteht, wenn die erste Transaktion versucht, dieselbe Zeile zu aktualisieren.In the previous example, the first transaction selects data, and a second transaction updates the data before the first transaction is able to complete, causing an update conflict when the first transaction tries to update the same row. Sie können die Gefahr von Updatekonflikten in Snapshot-Transaktionen mit langen Laufzeiten reduzieren, indem Sie zu Beginn der Transaktionen Sperrhinweise bereitstellen.You can reduce the chance of update conflicts in long-running snapshot transactions by supplying lock hints at the beginning of the transaction. In der folgenden SELECT-Anweisung wird der UPDLOCK-Hinweis zum Sperren der ausgewählten Zeilen verwendet:The following SELECT statement uses the UPDLOCK hint to lock the selected rows:

SELECT * FROM TestSnapshotUpdate WITH (UPDLOCK)   
  WHERE PriKey BETWEEN 1 AND 3  

Mit dem UPDLOCK-Sperrhinweis werden alle Zeilen blockiert, die versuchen, die Zeilen vor dem Fertigstellen der ersten Transaktion zu aktualisieren.Using the UPDLOCK lock hint blocks any rows attempting to update the rows before the first transaction completes. Dadurch wird gewährleistet, dass die ausgewählten Zeilen fehlerfrei sind, wenn sie später in der Transaktion aktualisiert werden.This guarantees that the selected rows have no conflicts when they are updated later in the transaction. Weitere Informationen finden Sie in der Onlinedokumentation zu SQL Server unter "Locking Hints".See "Locking Hints" in SQL Server Books Online.

Wenn eine Anwendung viele Konflikte aufweist, stellt die Snapshot-Isolation möglicherweise nicht die optimale Vorgehensweise dar.If your application has many conflicts, snapshot isolation may not be the best choice. Hinweise sollten nur verwendet werden, wenn sie wirklich erforderlich sind.Hints should only be used when really needed. Eine Anwendung sollte nicht so erstellt werden, dass ihre Ausführung stets von Sperrhinweisen abhängt.Your application should not be designed so that it constantly relies on lock hints for its operation.

Siehe auchSee Also

SQL Server und ADO.NETSQL Server and ADO.NET
ADO.NET Managed Provider und DataSet Developer CenterADO.NET Managed Providers and DataSet Developer Center