System.Data.SQLite不支持多个事务

所以我在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行(声明第二个事务)失败,但有以下exception:

 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有一个非常精细的锁定系统,该系统针对具有多个读取器或单个读取器/写入器线程的场景进行了优化。 因此,众所周知,并发写入存在性能问题 – 它并不是设计用于具有许多concurent writer的应用程序 。 您可以执行并发写入,但它不能很好地扩展。

在这种情况下,问题是因为您正在尝试进行并发模式更改 – 如果您改为执行多个SELECT或多个INSERT语句,那么这成功运行(如sixfeetsix的答案所示)。

如果您的应用程序有很多读者而不是很多编写者,那么SQLite可能会很好,但是如果您的应用程序包含许多并发读取器和编写那么您可能会发现完全成熟的数据库服务器更合适。

有关更多详细信息,请参阅SQLite版本3中的文件锁定和并发 。

尝试使用:

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

bool参数讲述了deferredLock。 但是,请记住,只有在提交第一个事务后才应调用ExecuteNonScalar。

对于它的价值而言,不支持每个连接的多个事务似乎对数据提供者来说很常见(我肯定知道ODP.NET,可能是其他人)。

解决此问题的一种方法是为每个单独的IDbTransaction分别设置一个IDbConnection

– 编辑—

卫生署! 我刚刚意识到你确实有多个联系。 抱歉。

SQLite不支持多个事务 – 它在事务中锁定整个数据库(请参阅www.sqlite.org)。

编辑:支持多个事务,但在多个事务中使用DDL时不支持。