Aracılığıyla paylaş


Hareketler

İşlemler, birden çok SQL deyimini tek bir atomik birim olarak veritabanına kaydedilmiş tek bir iş birimi halinde gruplandırmanıza olanak tanır. İşlemdeki herhangi bir deyim başarısız olursa, önceki deyimler tarafından yapılan değişiklikler geri alınabilir. İşlemin başlatıldığı veritabanının ilk durumu korunur. Bir işlem kullanmak, veritabanında aynı anda çok sayıda değişiklik yaparken SQLite performansını da artırabilir.

Eşzamanlılık

SQLite'te, veritabanında aynı anda yalnızca bir işlemin bekleyen değişiklikleri olmasına izin verilir. Bu nedenle, başka bir işlemin tamamlanması çok uzun sürerse ve Execute üzerindeki SqliteCommand yöntemlerin çağrıları BeginTransaction zaman aşımına uyabilir.

Kilitleme, yeniden denemeler ve zaman aşımları hakkında daha fazla bilgi için bkz . Veritabanı hataları.

Yalıtım düzeyleri

İşlemler SQLite'te varsayılan olarak serileştirilebilir . Bu yalıtım düzeyi, bir işlem içinde yapılan tüm değişikliklerin tamamen yalıtılmış olduğunu garanti eder. İşlemin dışında yürütülen diğer deyimler, işlemin değişikliklerinden etkilenmez.

SQLite, paylaşılan önbellek kullanılırken okunmamış okumayı da destekler. Bu düzey kirli okumalara, güncelleştirilemeyen okumalara ve hayaletlere izin verir:

  • Bir işlemde bekleyen değişiklikler işlemin dışındaki bir sorgu tarafından döndürülür ancak işlemdeki değişiklikler geri alındığında kirli bir okuma gerçekleşir. Sonuçlar, veritabanına hiçbir zaman işlenmeyen veriler içerir.

  • Bir işlem aynı satırı iki kez sorguladığında güncelleştirilemeyen bir okuma gerçekleşir, ancak sonuçlar farklı olur çünkü iki sorgu arasında başka bir işlem tarafından değiştirildi.

  • Hayaletler , bir işlem sırasında sorgunun where yan tümcesini karşılamak için değiştirilen veya eklenen satırlardır. İzin verilirse, aynı sorgu aynı işlemde iki kez yürütülürken farklı satırlar döndürebilir.

Microsoft.Data.Sqlite, 'a geçirilen IsolationLevel'i BeginTransaction en düşük düzey olarak kabul eder. Gerçek yalıtım düzeyi, okunmamış veya serileştirilebilir olarak yükseltilecektir.

Aşağıdaki kod, kirli bir okumanın benzetimini yapar. bağlantı dizesi içermesi Cache=Sharedgerektiğini unutmayın.

using (var firstTransaction = firstConnection.BeginTransaction())
{
    var updateCommand = firstConnection.CreateCommand();
    updateCommand.CommandText =
    @"
        UPDATE data
        SET value = 'dirty'
    ";
    updateCommand.ExecuteNonQuery();

    // Without ReadUncommitted, the command will time out since the table is locked
    // while the transaction on the first connection is active
    using (secondConnection.BeginTransaction(IsolationLevel.ReadUncommitted))
    {
        var queryCommand = secondConnection.CreateCommand();
        queryCommand.CommandText =
        @"
            SELECT *
            FROM data
        ";
        var value = (string)queryCommand.ExecuteScalar();
        Console.WriteLine($"Value: {value}");
    }

    firstTransaction.Rollback();
}

Ertelenen işlemler

Microsoft.Data.Sqlite sürüm 5.0'dan itibaren işlemler ertelenebilir. Bu, ilk komut yürütülene kadar veritabanında gerçek işlemin oluşturulmasını saptırılır. Ayrıca, işlemin bir okuma işleminden komutlarının gerektirdiği şekilde aşamalı olarak bir yazma işlemine yükseltmesine neden olur. Bu işlem sırasında veritabanına eşzamanlı erişimi etkinleştirmek için yararlı olabilir.

using (var transaction = connection.BeginTransaction(deferred: true))
{
    // Before the first statement of the transaction is executed, both concurrent
    // reads and writes are allowed

    var readCommand = connection.CreateCommand();
    readCommand.CommandText =
    @"
        SELECT *
        FROM data
    ";
    var value = (long)readCommand.ExecuteScalar();

    // After a the first read statement, concurrent writes are blocked until the
    // transaction completes. Concurrent reads are still allowed

    var writeCommand = connection.CreateCommand();
    writeCommand.CommandText =
    @"
        UPDATE data
        SET value = $newValue
    ";
    writeCommand.Parameters.AddWithValue("$newValue", value + 1L);
    writeCommand.ExecuteNonQuery();

    // After the first write statement, both concurrent reads and writes are blocked
    // until the transaction completes

    transaction.Commit();
}

Uyarı

Ertelenen işlem içindeki komutlar, veritabanı kilitliyken işlemin okuma işleminden yazma işlemine yükseltilmesine neden olursa başarısız olabilir. Böyle bir durumda uygulamanın tüm işlemi yeniden denemesi gerekir.

Savepoints

Microsoft.Data.Sqlite sürüm 6.0, kayıt noktalarını destekler. İç içe işlemler oluşturmak için kayıt noktaları kullanılabilir. Kayıt noktaları, işlemin diğer bölümleri etkilenmeden geri alınabilir ve bir kayıt noktası işlenebilir (serbest bırakılabilir) olsa bile, değişiklikleri daha sonra üst işleminin bir parçası olarak geri alınabilir.

Aşağıdaki kod, eşzamanlı güncelleştirmeleri algılamak ve daha büyük bir işlemin parçası olarak bir kayıt noktası içindeki çakışmaları çözmek için İyimser Çevrimdışı Kilit düzeninin kullanılmasını gösterir.

using (var transaction = connection.BeginTransaction())
{
    // Transaction may include additional statements before the savepoint

    var updated = false;
    do
    {
        // Begin savepoint
        transaction.Save("optimistic-update");

        var insertCommand = connection.CreateCommand();
        insertCommand.CommandText =
        @"
            INSERT INTO audit
            VALUES (datetime('now'), 'User updates data with id 1')
        ";
        insertCommand.ExecuteScalar();

        var updateCommand = connection.CreateCommand();
        updateCommand.CommandText =
        @"
            UPDATE data
            SET value = 2,
                version = $expectedVersion + 1
            WHERE id = 1
                AND version = $expectedVersion
        ";
        updateCommand.Parameters.AddWithValue("$expectedVersion", expectedVersion);
        var recordsAffected = updateCommand.ExecuteNonQuery();
        if (recordsAffected == 0)
        {
            // Concurrent update detected! Rollback savepoint and retry
            transaction.Rollback("optimistic-update");

            // TODO: Resolve update conflicts
        }
        else
        {
            // Update succeeded. Commit savepoint and continue with the transaction
            transaction.Release("optimistic-update");

            updated = true;
        }
    }
    while (!updated);

    // Additional statements may be included after the savepoint

    transaction.Commit();
}