【问题标题】:Locking problems with sqlite and SubSonic when using transactions on a single thread在单线程上使用事务时,sqlite 和 SubSonic 的锁定问题
【发布时间】:2010-02-18 19:01:27
【问题描述】:

我在尝试将事务与 SubSonic 和 SQLite 一起使用时遇到锁定异常。我从一个线程中使用它,并且没有其他进程访问我的数据库,所以我真的没想到会出现任何此类问题。

如果我在下面编写这样的代码,我会在循环内第二次调用 Save() 时遇到异常 - 所以第三次调用 Save() 总之。

       using (TransactionScope ts = new TransactionScope())
       {
            using (SharedDbConnectionScope sharedConnectinScope = new SharedDbConnectionScope())
            { 
                SomeDALObject x = new SomeDALObject()
                x.Property1 = "blah";
                x.Property2 = "blah blah";
                x.Save();

                foreach (KeyValuePair<string, string> attribute in attributes)
                { 
                    AnotherDALObject y = new AnotherDALObject()
                    y.Property1 = attribute.Key
                    y.Property2 = attribute.Value
               
                    y.Save();  // this is where the exception is raised, on the 2nd time through this loop
                }
            }
       }

如果我有上面的 using() 语句,或者如果我只有 using (TransactionScope ts = new TransactionScope()),那么我会收到带有消息的 System.Data.SQLite.SQLiteException

数据库文件被锁定

数据库被锁定

堆栈跟踪是:

   at System.Data.SQLite.SQLite3.Step(SQLiteStatement stmt)
   at System.Data.SQLite.SQLiteDataReader.NextResult()
   at System.Data.SQLite.SQLiteDataReader..ctor(SQLiteCommand cmd, CommandBehavior behave)
   at System.Data.SQLite.SQLiteCommand.ExecuteReader(CommandBehavior behavior)
   at System.Data.SQLite.SQLiteCommand.ExecuteNonQuery()
   at System.Data.SQLite.SQLiteTransaction..ctor(SQLiteConnection connection, Boolean deferredLock)
   at System.Data.SQLite.SQLiteConnection.BeginDbTransaction(IsolationLevel isolationLevel)
   at System.Data.SQLite.SQLiteConnection.BeginTransaction()
   at System.Data.SQLite.SQLiteEnlistment..ctor(SQLiteConnection cnn, Transaction scope)
   at System.Data.SQLite.SQLiteConnection.EnlistTransaction(Transaction transaction)
   at System.Data.SQLite.SQLiteConnection.Open()
   at SubSonic.SQLiteDataProvider.CreateConnection(String newConnectionString)
   at SubSonic.SQLiteDataProvider.CreateConnection()
   at SubSonic.SQLiteDataProvider.ExecuteScalar(QueryCommand qry)
   at SubSonic.DataService.ExecuteScalar(QueryCommand cmd)
   at SubSonic.ActiveRecord`1.Save(String userName)
   at SubSonic.ActiveRecord`1.Save()
   at (my line of code above).

如果我将 using 语句嵌套在另一个方向上,SharedDbConnectionScope 在外部,那么我会收到 TransactionException 消息“该操作对事务状态无效。”堆栈跟踪是:

at System.Transactions.TransactionState.EnlistVolatile(InternalTransaction tx, IEnlistmentNotification enlistmentNotification, EnlistmentOptions enlistmentOptions, Transaction atomicTransaction)
   at System.Transactions.Transaction.EnlistVolatile(IEnlistmentNotification enlistmentNotification, EnlistmentOptions enlistmentOptions)
   at System.Data.SQLite.SQLiteEnlistment..ctor(SQLiteConnection cnn, Transaction scope)
   at System.Data.SQLite.SQLiteConnection.EnlistTransaction(Transaction transaction)
   at System.Data.SQLite.SQLiteConnection.Open()
   at SubSonic.SQLiteDataProvider.CreateConnection(String newConnectionString)
   at SubSonic.SQLiteDataProvider.CreateConnection()
   at SubSonic.SQLiteDataProvider.ExecuteScalar(QueryCommand qry)
   at SubSonic.DataService.ExecuteScalar(QueryCommand cmd)
   at SubSonic.ActiveRecord`1.Save(String userName)
   at SubSonic.ActiveRecord`1.Save()
   at (my line of code above)

内部异常是“事务超时”

我在生成的 DAL 类中没有任何自定义代码,或者我能想到的任何其他聪明的东西都会导致这种情况。

其他人遇到过这样的交易问题,或者有人可以建议我从哪里开始寻找问题?

谢谢!

更新:我注意到版本 1.0.61-65 的发行说明中提到了与事务相关的内容(例如 here),因此更新 SubSonic 以使用最新版本的 .Net 数据提供程序可能会解决一些问题这些问题...

【问题讨论】:

    标签: .net sqlite subsonic transactions subsonic2.2


    【解决方案1】:

    在为 subsonic 2.x 进行修订的 sqlite 提供程序时,我基于现有的 subsonic sqlserver 测试创建了一套完整的单元测试。 (这些测试也使用修改后的代码进行了检查。)唯一失败的测试是与事务相关的测试(也可能是迁移测试)。如您所见,“数据库文件已锁定”错误消息。 Subsonic 主要是为 sql server 编写的,它不像 SQLIte 那样做文件级锁定,所以有些东西不起作用;它需要重写才能更好地处理。

    我从来没有像你那样使用过 TransactionScope。我像这样进行亚音速 2.2 事务,到目前为止 SQLite 提供程序没有问题。如果要处理多行,我可以确认您需要使用 SQLite 事务,否则它真的很慢。

    public void DeleteStuff(List<Stuff> piaRemoves)
    {
        QueryCommandCollection qcc = new QueryCommandCollection();
    
        foreach(Stuff item in piaRemoves)
        {
            Query qry1 = new Query(Stuff.Schema);
            qry1.QueryType = QueryType.Delete;
            qry1.AddWhere(Stuff.Columns.ItemID, item.ItemID);
            qry1.AddWhere(Stuff.Columns.ColumnID, item.ColumnID);
            qry1.AddWhere(Stuff.Columns.ParentID, item.ParentID);
            QueryCommand cmd = qry1.BuildDeleteCommand();
            qcc.Add(cmd);
        }
        DataService.ExecuteTransaction(qcc);
    }
    

    【讨论】:

    【解决方案2】:

    我最终使用了 Paul 的建议并将我的代码重写为如下内容:

        QueryCommandCollection qcc = new QueryCommandCollection();
    
        SomeDALObject x = new SomeDALObject()
        x.Property1 = "blah";
        x.Property2 = "blah blah";
        qcc.Add(x.GetSaveCommand());
    
        foreach (KeyValuePair<string, string> attribute in attributes)
        { 
            AnotherDALObject y = new AnotherDALObject()
            y.Property1 = attribute.Key
            y.Property2 = attribute.Value
    
            qcc.Add(y.GetSaveCommand());
        }
    
        DataService.ExecuteTransaction(qcc);
    

    这实际上要好得多,因为数据库命中的所有准备工作都在事务打开之前完成,因此事务打开的时间要少得多。

    如果您需要取回自动生成的 ID 以便为子记录运行 INSERT,这将无法正常工作;您需要为此使用不同的方法。

    然后我遇到了其他一些线程/事务问题:当我有多个线程同时执行 DataService.ExecuteTransaction() 时,我会得到 AccessViolationExceptions 和 NullReferenceExceptions,基本上有点乱。但是更改为使用 Paul's fork 的 SubSonic 和更新的 SQLDataProvider 并更改为使用 System.Data.SQLite v1.0.65.0 似乎立即修复了它。万岁!

    更新:实际上我在使用 SubSonic 和 sqlite 时仍然遇到线程问题。基本上,SubSonic 中的 SQLiteDataProvider 并不是为了处理多线程而编写的。更多内容...

    【讨论】:

      【解决方案3】:

      我们正在使用 SQL lite 来测试与数据库操作相关的代码。 SQL lite 不支持嵌套事务。 我们在 NHibernate 和 .Net 事务中遇到了类似的问题。 最终我们不得不使用 SQL Express 来测试数据库相关代码。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-09-03
        • 1970-01-01
        • 1970-01-01
        • 2012-03-08
        相关资源
        最近更新 更多