尽pipe使用内容提供者和顺序数据库访问,android sqlite“数据库被locking”错误

我有一个应用程序(Android 2.2谷歌API级别8),有多个活动从内容提供者(只select数据库访问)拉动数据。 它也有一个中央阻塞任务队列接受任何数据库写入任务的服务; 活动可以触发一个服务请求(As intent),它将一个任务放置在一个阻塞队列上,以便通过一个单独的线程进行顺序检索并执行。 数据库大概是4MB。

有一个数据库帮助,服务用来调用方法来与数据库交互,包括写入数据库; 所有的SQL写入都在数据库帮助程序中执行。

  • 所有数据库写入都被一个事务包围。
  • 所有数据库读取都在方法结束时closures游标。
  • 这些活动都没有数据库对象的句柄,它们只能通过内容提供者或服务进行通信。
  • 任何AlarmManager触发的任务(如“活动”)只能使用该服务将适当的任务popup到队列中。
  • 该服务是唯一具有数据库帮助程序句柄的类。
  • 所有的数据库写操作只能通过放置在队列中的任务来执行; 我已经彻底地检查了任务执行是顺序的,因为它很好地避免了对SQLite数据库的并发写入。

在执行任务的过程中,在尝试写入由“begin transaction”的任务执行触发的数据库时,我始终得到一个或两个“数据库已locking”错误。

在试图追踪锁的来源时,我发现使用dbhelper.inTransaction(),dbhelper.isLockedByThisThread(),dbhelper.isLockedByOtherThread()没有帮助,因为它们不会指示意外的数据库locking。

我所发现的在早期检测locking的方法是在一个try catch块中创build一个beginTransaction()和setTransactionSuccessful方法,但没有任何实际的SQL编写代码,它会logging这个问题 – 总是由beginTransaction()触发。

我把这个数据库锁陷阱放在每个阻塞队列任务方法的任一侧,期望/希望我会find一个奇怪的罪魁祸首,完成后,数据库处于locking状态。 我无法find一个一致的罪魁祸首。 从任务调用开始直到数据库写入之后,我发现数据库锁可能会在没有被先前运行的任务locking的情况下出现在蓝色的外面(所有这些任务在相同单数线程中依次运行)。

查看了一些其他人的数据库locking问题的经验之后,我试着在所有任务完成事务后直接closures数据库连接,但是这并没有帮助,如果有什么似乎得到更多的数据库locking事件。 尝试在每个任务执行之间添加一个睡眠; 没有详尽testing,但一般发现,3秒或以上的延迟似乎停止出现数据库锁。 试图禁用警报pipe理器开除任务 – 没有任何区别。

我的印象是,我的应用程序外部的某种forms的维护任务正在放入并定期locking数据库 – 可能会延迟写入日志。 显然,我不太热衷于设置任务处理延迟,所以我正在考虑让数据库锁重试任务队列重新尝试数据库写入, 更喜欢解决,但是用尽了想法。

任何人都可以想到我已经错过的一些原则或难题?

在Android和更大的SQLite数据库中是否实际上是正常的,你会偶尔发现数据库锁?

谢谢

Solutions Collecting From Web of "尽pipe使用内容提供者和顺序数据库访问,android sqlite“数据库被locking”错误"

只要你使用单一的数据库连接,SQLite保证从多个线程的顺序访问。 如何以及在哪里打开和closures数据库连接?

我通常build议在启动时打开一次数据库,而不要closures它。 closures没有任何好处,因为SQLite的事务特性意味着尽可能快地将写入刷新到持久性存储。

我会检查一些调用数据库或调用其他调用数据库的活动是否只有一个实例。 而在某种意义上,它可以locking自己。

关于

在Android和更大的SQLite数据库中是否实际上是正常的,你会偶尔发现数据库锁?

没有,偶尔的数据库locking绝对不是正常的。 从阅读你的故事,你说你有一个服务和一个内容提供者从数据库拉,所以你可能会在两次访问之间locking数据库。

我通常所做的是确保我通过内容提供者处理所有的数据库访问。 通过对数据库进行单点login,可以确保每个软件组件都使用相同的逻辑访问数据库。 是否有可能通过内容提供商访问数据库?

最好还是记住,将数据库放置在内容提供者之后,它仍然可以被多个线程同时访问。 为了确保您一次只访问一个线程,可以将同步的结构放在内容提供者的数据库中。 显然,如果你正在做大量的长时间的写入/读取数据库,以这种方式locking将绝对破坏你的应用程序。 把所有的数据库代码放在内容提供者的内部也会给你一个debugging点,它可以帮助你确定是否有多个线程正在访问数据库。