【问题标题】:Does it allow to create many transactions at a time in Android SQLite它是否允许在 Android SQLite 中一次创建多个事务
【发布时间】:2012-02-12 18:57:30
【问题描述】:

阅读this document,它说SQLite 支持事务和嵌套事务。我想知道是否可以创建许多不同的交易。

例如:我有 2 个线程访问数据库连接,是否可以在每个线程上创建一个事务并且它们不嵌套?

【问题讨论】:

    标签: android multithreading sqlite transactions


    【解决方案1】:

    Sqlite does not support nested transactions:

    使用 BEGIN...COMMIT 创建的事务不嵌套。对于嵌套 事务,请使用 SAVEPOINT 和 RELEASE 命令。

    我自己在使用带有 SQLiteDatabase 类的嵌套事务时遇到过死锁,因此我强烈建议您远离嵌套事务。使用您自己的锁来防止您的事务嵌套。

    【讨论】:

      【解决方案2】:

      在两个单独的线程上创建两个单独的事务不被视为“嵌套事务”。

      每个线程都维护自己的数据库会话,该会话映射到 0 或 1 个数据库连接(可以从连接池中选择一个数据库连接,如果会话不再需要该连接,则将其返回给它,所以在任何时候,会话是否有连接,取决于它是否需要)。

      因此,每个线程都独立于其他线程维护自己的事务状态。消息来源证实了这一点:

      ../Android/sdk/sources/android-23/android/database/sqlite/SQLiteDatabase.java:

      // Thread-local for database sessions that belong to this database.
      // Each thread has its own database session.
      // INVARIANT: Immutable.
      private final ThreadLocal<SQLiteSession> mThreadSession = new ThreadLocal<SQLiteSession>() {
          @Override
          protected SQLiteSession initialValue() {
              return createSession();
          }
      };
      

      ../Android/sdk/sources/android-23/android/database/sqlite/SQLiteSession.java:

       * <h2>About database sessions</h2>
       * <p>
       * Database access is always performed using a session.  The session
       * manages the lifecycle of transactions and database connections.
       * </p><p>
      

      ...

      * Consequently, each thread
       * has its own session object and therefore its own transaction state independent
       * of other threads.
      

      因此,如果您有两个事务在单独的线程中进行,它们不是“嵌套”的,而是完全独立的,并且将并行运行或序列化,具体取决于所涉及事务的模式和类型(即它们是否被延迟,立即、独占以及它们是读还是写)。

      但是,必须正确使用 Android SQLite 库才能实现此目的。

      我有 2 个线程访问数据库连接

      如果这意味着两个线程都使用同一个 SQLiteSession,(尽管我不确定如果可能的话,你如何实现这一点),那么这很可能会导致死锁。

      我的设置:

      1. 单一内容提供商
      2. Content Provider 在其 onCreate() 中为 SQLiteOpenHelper 初始化成员变量 mDbHelper
      3. 在 Content Provider 的 query/insert/ ... 方法中根据需要调用 mHelper.getReadableDatabase / getWriteableDatabase
      4. Android 将处理确保使用 Content Provider 的每个线程上的单独事务状态

      如果要在线程上执行长时间运行的事务(例如,从后台线程同步导入数据),请考虑使用 db.yieldIfContended()db.yieldIfContendedSafely() 以允许来自其他线程的事务(例如或在 UI 上记录更新thread) 挤进去,这样他们就不必等待长时间运行的事务完成并因此阻塞这些线程。

      【讨论】:

        猜你喜欢
        • 2016-09-27
        • 1970-01-01
        • 2010-11-21
        • 2021-01-18
        • 2021-06-12
        • 1970-01-01
        • 1970-01-01
        • 2017-06-25
        • 2018-04-20
        相关资源
        最近更新 更多