System.Data.SQLite不支持多事务

本文关键字:事务 不支持 SQLite Data System | 更新日期: 2023-09-27 18:02:26

所以我有一个有趣的问题与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()

有人知道问题是什么或如何解决这个问题吗?我觉得并发事务对任何数据库系统都是必不可少的,所以一定有办法做到这一点。

谢谢!

System.Data.SQLite不支持多事务

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可能很好,但是如果你的应用程序有很多并发读取器和写入器,那么你可能会发现一个成熟的数据库服务器更合适。

尝试使用:

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

bool形参表示deferredLock。但是,请记住,ExecuteNonScalar应该只在第一个事务提交之后调用。

无论如何,对于数据提供者来说,不支持每个连接的多个事务似乎很常见(我肯定知道ODP)。. NET,可能还有其他)。

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

—EDIT—

哎!我刚刚意识到你的有多个连接。对不起。

SQLite不支持多事务-在一个事务中它会锁定整个数据库(参见www.sqlite.org)。

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