【问题标题】:Multiple threading questions when using sqlite transaction in Android在 Android 中使用 sqlite 事务时的多线程问题
【发布时间】:2019-02-27 11:42:52
【问题描述】:

我在 Android 中使用 sqlite 事务:

SQLiteDatabase database = sqlite_helper.getWritableDatabase();

database.beginTransaction();
...
database.setTransactionSuccessful();
database.endTransaction();

我的问题是:
1.我应该把endTransaction()放在finally代码块中:

try {
    database.beginTransaction();
    ...
    database.setTransactionSuccessful();
}
finally {
    database.endTransaction();
}

如果在数据库操作过程中出现异常,数据库是否会自动回滚而不使用“finally”?

  1. 事务未结束时,其他线程能否读写同一个数据库?我听说 Android 中的 sqlite 是线程安全的,但我不确定。我想在交易过程中会有一些问题。如果另一个线程使用相同的连接写入相同的数据库,是否会引发错误?
    我曾经在我的应用程序中发现过这个错误,但我不知道它是否与线程安全问题有关:

android.database.sqlite.SQLiteMisuseException: library routine called out of sequence:

,编译时

有人帮我回答这些问题吗?非常感谢!

【问题讨论】:

    标签: android sqlite android-sqlite


    【解决方案1】:

    1.您应该始终将 endTransaction 放在 finally 块中

    2.SQLite 中的事务是线程安全的,参见文档http://www.sqlite.org/atomiccommit.html

    【讨论】:

    • 该链接没有提及“线程”一词。它是如何线程安全的?问题是另一个线程是否会在另一个线程的事务打开时创建新事务或运行新查询。那么它是线程安全的吗?根据我目前的经验,我遇到了奇怪的“连接池”错误。
    • 事务不是线程安全的。线程之间只有一个SQLiteDatabase实例共享,因此数据库只能处于一种事务状态,将由两个线程同时操作。如果一个线程开始一个事务,然后第二个线程尝试开始另一个事务,你会得到一个 IllegalStateException 抛出。
    • Android beginTransaction 和 endTransaction 是使用 Java 同步的实际 BEGIN 和 COMMIT 命令的线程安全包装函数,即使它在内部使用单个数据库连接。如果您直接使用原生 SQLite API(不太可能在 Android 中),则它不是线程安全的。
    【解决方案2】:

    您应该始终将endTransaction() 放入finally 块中(另请参阅the docs)。 否则,数据库将无法注意到发生了异常。

    结束事务的唯一其他方法是关闭连接,在这种情况下,SQLite 会自动回滚任何活动事务。

    只要一个连接写入数据库(这意味着事务处于活动状态),就没有其他连接可以读取或写入。因此,您应该注意不要忘记结束事务。

    你不应该从多个线程中写入;如果一个线程结束事务,而另一个线程仍在写,会发生什么?

    您的SQLiteMisuseException 可能相关,也可能不相关;没有看到代码就不可能这么说。

    【讨论】:

      【解决方案3】:

      是的,您应该使用 finally 块。这是我使用的一个简单的 THREAD SAFE 方法:

      /**
       * Call for multiple DB insertion transactions.  It is thread safe and fast!
       */
      private synchronized void writeTransaction(Runnable task) {
          try {
              db.beginTransaction();
              task.run();
              db.setTransactionSuccessful();
          } finally {
              db.endTransaction();
          }
      }
      

      synchronized 关键字将方法与其包含的对象锁定在一起,从而使其线程安全...

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2017-02-18
        • 1970-01-01
        • 2018-05-14
        • 1970-01-01
        • 2011-01-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多