【问题标题】:Transactions in multi threaded environment in SQLite WP 8.1SQLite WP 8.1 中多线程环境中的事务
【发布时间】:2015-03-09 06:43:38
【问题描述】:

我在以下场景中使用 SQLite 时遇到问题。

有两个线程在数据库上工作。

两个线程都必须在事务中插入消息。

如果说一个线程在插入 20k 行后提交,而其他线程尚未提交。

在输出中,我看到线程 2 插入的所有数据都已提交,直到线程 1 提交数据为止。

示例函数:

    /// <summary>
    /// Inserts list of messages in message table
    /// </summary>
    /// <param name="listMessages"></param>
    /// <returns></returns>
    public bool InsertMessages(IList<MessageBase> listMessages, bool commitTransaction)
    {
        bool success = false;

        if (listMessages == null || listMessages.Count == 0)
            return success;

        DatabaseHelper.BeginTransaction(_sqlLiteConnection);


        foreach (MessageBase message in listMessages)
        {
            using (var statement = _sqlLiteConnection.Prepare(_insertMessageQuery))
            {

                BindMessageData(message, statement);

                SQLiteResult result = statement.Step();
                success = result == SQLiteResult.DONE;


                if (success)
                {
                    Debug.WriteLine("Message inserted suucessfully,messageId:{0}, message:{1}", message.Id, message.Message);
                }
                else
                {
                    Debug.WriteLine("Message failed,Result:{0}, message:{1}", result, message.Message);
                }
            }
        }
        if (commitTransaction)
        {
            Debug.WriteLine("Data committed");
            DatabaseHelper.CommitTransaction(_sqlLiteConnection);
        }
        else
        {
            Debug.WriteLine("Data not committed");
        }

        return success;
    }

有什么方法可以阻止线程 2 插入的提交事务?

【问题讨论】:

  • 您是否打开了 2 个数据库连接,每个线程一个,且禁用了 shared_cache?
  • 我为两个线程使用相同的数据库连接,并保持在整个应用程序中打开的单个数据库连接。

标签: multithreading sqlite transactions windows-phone-8.1


【解决方案1】:

简而言之,在单个数据库上是不可能的。

单个 sqlite 数据库不能同时拥有多个具有不同事务上下文的写入者。 sqlite 数据库也没有每个连接单独的上下文;要获得上下文,您需要建立新的连接。但是,一旦您使用插入(或更新/删除)开始初始写入,事务需要在数据库上保留一个锁定(允许读取器,没有其他写入器),这意味着并行写入是不可能的。我想你也许可以用SAVEPOINTRELEASE 来伪造它,但它们也在连接上序列化并且不会生成单独的上下文。

考虑到这一点,您可以使用通过ATTACH DATABASE 连接的单独数据库,只要两个线程不写入同一个表即可。为此,您将在运行时附加包含其他表的附加数据库。但是,您仍然需要为每个并行写入器建立一个单独的连接,因为对连接的提交仍然适用于所有打开的事务。

否则,您可以通过打开一个额外的连接来获得单独的事务,而以后的连接和事务将只需要等待直到 RESERVED 锁被释放。

参考资料:

【讨论】:

    猜你喜欢
    • 2012-06-26
    • 2018-02-23
    • 1970-01-01
    • 1970-01-01
    • 2020-07-11
    • 1970-01-01
    • 1970-01-01
    • 2018-05-14
    • 1970-01-01
    相关资源
    最近更新 更多