簡體   English   中英

System.Data.SQLite 不支持多個事務

[英]System.Data.SQLite Not Supporting Multiple Transactions

所以我對 System.Data.SQLite 和使用多個事務有一個有趣的問題。 基本上我有以下代碼失敗:

using (IDbConnection connection1 = new SQLiteConnection("connectionstring"), connection2 = new SQLiteConnection("connectionstring"))
{
    connection1.Open();
    connection2.Open();

    IDbTransaction transaction1 = connection1.BeginTransaction();
    IDbTransaction transaction2 = connection2.BeginTransaction();    // Fails!

    using(IDbCommand command = new SQLiteCommand())
    {
        command.Text = "CREATE TABLE artist(artistid int, artistname text);";
        command.CommandType = CommandType.Text;
        command.Connection = connection1;
        command.ExecuteNonQuery();
    }

    using (IDbCommand command = new SQLiteCommand())
    {
        command.Text = "CREATE TABLE track(trackid int, trackname text);";
        command.CommandType = CommandType.Text;
        command.Connection = connection2;                    
        command.ExecuteNonQuery();
    }

    transaction1.Commit();
    transaction2.Commit();

}

從我讀到的似乎 System.Data.SQLite 應該支持嵌套和擴展順序事務。 代碼在第 7 行(聲明第二個事務)失敗,但有以下異常:

System.Data.SQLite.SQLiteException: The database file is locked

System.Data.SQLite.SQLite3.Step(SQLiteStatement stmt)
System.Data.SQLite.SQLiteDataReader.NextResult()
System.Data.SQLite.SQLiteDataReader..ctor(SQLiteCommand cmd, CommandBehavior behave)
System.Data.SQLite.SQLiteCommand.ExecuteReader(CommandBehavior behavior)
System.Data.SQLite.SQLiteCommand.ExecuteNonQuery()
System.Data.SQLite.SQLiteTransaction..ctor(SQLiteConnection connection, Boolean deferredLock)
System.Data.SQLite.SQLiteConnection.BeginDbTransaction(IsolationLevel isolationLevel)
System.Data.Common.DbConnection.System.Data.IDbConnection.BeginTransaction()

有誰知道問題是什么或如何解決這個問題? 我覺得擁有並發事務對於任何數據庫系統都是必不可少的,因此必須有某種方法來做到這一點。

謝謝!

OP 在 2 個連接上啟動事務,這就是問題開始的地方,而不是多個事務本身。

SQLiteConnection conn = new SQLiteConnection("data source=:memory:");
conn.Open();

var command = conn.CreateCommand();
command.CommandText = "create table a (b integer primary key autoincrement, c text)";
command.ExecuteNonQuery();

var tran1 = conn.BeginTransaction();
var tran2 = conn.BeginTransaction();

var command1 = conn.CreateCommand();
var command2 = conn.CreateCommand();

command1.Transaction = tran1;
command2.Transaction = tran2;

command1.CommandText = "insert into a VALUES (NULL, 'bla1')";
command2.CommandText = "insert into a VALUES (NULL, 'bla2')";

command1.ExecuteNonQuery();
command2.ExecuteNonQuery();

tran1.Commit();
tran2.Commit();

command.CommandText = "select count(*) from a";
Console.WriteLine(command.ExecuteScalar());

SQLite 被設計為一個輕量級數據庫,用於存儲瀏覽器中的書簽或照片目錄程序中的照片等內容。 SQLite 有一個非常精細的鎖定系統,它針對具有多個讀取器或單個讀取器/寫入器線程的場景進行了優化。 因此,眾所周知,並發寫入存在性能問題 -它根本不適合在具有許多並發寫入者的應用程序中使用 您可以進行並發寫入,但不能很好地擴展。

在這種情況下,問題是因為您正在嘗試進行並發架構更改 - 如果您改為執行多個SELECT或多個INSERT語句,那么這成功運行(如 Sixfeetsix 的答案所示)。

如果您的應用程序有很多讀取器而寫入器不多,那么 SQLite 可能很好,但是如果您的應用程序具有許多並發讀取器寫入器,那么您可能會發現成熟的數據庫服務器更合適。

有關詳細信息,請參閱SQLite 第 3 版中的文件鎖定和並發

嘗試使用:

((SQLiteConnection)connection).BeginTransaction(true)-

bool 參數說明 deferredLock。 但是,請記住 ExecuteNonScalar 僅應在提交第一個事務后調用。

就其價值而言,對於數據提供者來說,每個連接不支持多個事務似乎很常見(我肯定知道 ODP.NET,可能還有其他人)。

一種解決方法是為每個單獨的IDbTransaction設置一個單獨的IDbConnection

- 編輯 - -

嗬! 我剛剛意識到你確實有多個連接。 對不起。

SQLite 不支持多事務 - 它在事務中鎖定整個數據庫(請參閱 www.sqlite.org)。

編輯:支持多個事務,但在多個事務中使用 DDL 時不支持。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM