[英]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.