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=Shared
gerektiğ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();
}