Android SQLite事务和多线程

Imo*_*tep 5 sqlite multithreading android transactions android-sqlite

在我的应用程序中,我调用了一些Web服务来更新数据库。每个Web服务调用都是在特定线程中进行的,从而导致多个线程“一次”更新数据库对象。

在每个线程中,我都使用类似的事务:

Thread 1 (webservice 1)
beginTransaction()
insert a row in the table 1
update a row in the table 1
endTransaction()

Thread 2 (webservice 2)
beginTransaction()
update a row in the table 2
update a row in the table 2
endTransaction()
Run Code Online (Sandbox Code Playgroud)

但是我遇到一个问题,在谷歌搜索后我无法回答自己。由于事务是在不同的线程中处理的,它们是否彼此不同?换句话说,数据库使用的是单独的“声明堆栈”还是公共的?

从我的阅读中,我了解到事务在同一堆栈中,即在线程1中提交事务可能会提交表2上的更新。例如,我认为可能发生的DB语句堆栈:

beginTransaction() //Thread 1 begins a transaction
insert a row in the table 1
update a row in the table 1
beginTransaction() //Thread 2 begins a transaction
update a row in the table 2
update a row in the table 2
endTransaction() //Thread 2 ends a transaction
endTransaction() //Thread 1 ends a transaction
Run Code Online (Sandbox Code Playgroud)

如果是真的,我该如何使我的交易真正排他?我是否必须BEGIN EXCLUSIVE TRANSACTIONSQLITE_BUSY任何地方都应对错误,还是有更简单的方法?

小智 1

我鼓励进一步阅读以了解交易模式的工作原理。来自 SQLite 用户指南:

交易可以是延迟的、立即的或独占的。默认事务行为是延迟的。延迟意味着在第一次访问数据库之前不会获取数据库上的锁。因此,对于延迟事务,BEGIN 语句本身不会对文件系统执行任何操作。直到第一次读或写操作时才会获取锁。针对数据库的第一个读取操作会创建一个共享锁,而第一个写入操作会创建一个保留锁。由于锁的获取被推迟到需要时为止,因此另一个线程或进程可能会在当前线程上的 BEGIN 执行后创建单独的事务并写入数据库。如果事务是立即的,则一旦执行 BEGIN 命令,就会在所有数据库上获取 RESERVED 锁,而无需等待数据库被使用。在 BEGIN IMMEDIATE 之后,其他数据库连接将无法写入数据库或执行 BEGIN IMMEDIATE 或 BEGIN EXCLUSIVE。然而,其他进程可以继续从数据库中读取数据。独占事务会导致在所有数据库上获取独占锁。在 BEGIN EXCLUSIVE 之后,除了 read_uncommissed 连接之外,任何其他数据库连接都将无法读取数据库,并且任何其他连接无一例外都无法写入数据库,直到事务完成。

https://www.sqlite.org/lang_transaction.html

Android API 提供了一种处理这些事务模式的方法,因此请选择更适合您的应用程序的方法。

http://developer.android.com/reference/android/database/sqlite/SQLiteDatabase.html

  • “没有其他连接无一例外都能够写入数据库”当他们尝试时会发生什么?它会抛出异常吗?返回空结果?队列?我假设队列,但是队列公平吗?还是未指定? (2认同)