在 Android 上使用 SQLite 时如何避免并发问题? [英] How can I avoid concurrency problems when using SQLite on Android?

查看:32
本文介绍了在 Android 上使用 SQLite 时如何避免并发问题?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在 Android 应用中对 SQLite 数据库执行查询时,哪些最佳实践被视为最佳实践?

What would be considered the best practices when executing queries on an SQLite database within an Android app?

从 AsyncTask 的 doInBackground 运行插入、删除和选择查询是否安全?还是应该使用 UI 线程?我认为数据库查询可能是繁重的",不应使用 UI 线程,因为它会锁定应用程序 - 导致 应用程序无响应 (ANR).

Is it safe to run inserts, deletes and select queries from an AsyncTask's doInBackground? Or should I use the UI Thread? I suppose that database queries can be "heavy" and should not use the UI thread as it can lock up the app - resulting in an Application Not Responding (ANR).

如果我有多个 AsyncTask,它们应该共享一个连接还是每个都打开一个连接?

If I have several AsyncTasks, should they share a connection or should they open a connection each?

是否有针对这些场景的最佳做法?

Are there any best practices for these scenarios?

推荐答案

从多线程插入、更新、删除和读取一般都可以,但是 Brad 的 答案 不正确.您必须小心创建和使用连接的方式.在某些情况下,即使您的数据库没有损坏,您的更新调用也会失败.

Inserts, updates, deletes and reads are generally OK from multiple threads, but Brad's answer is not correct. You have to be careful with how you create your connections and use them. There are situations where your update calls will fail, even if your database doesn't get corrupted.

基本答案.

SqliteOpenHelper 对象保持一个数据库连接.它似乎为您提供了读写连接,但实际上并没有.调用只读,无论如何你都会得到写数据库连接.

The SqliteOpenHelper object holds on to one database connection. It appears to offer you a read and write connection, but it really doesn't. Call the read-only, and you'll get the write database connection regardless.

所以,一个辅助实例,一个数据库连接.即使您从多个线程使用它,一次一个连接.SqliteDatabase 对象使用java 锁来保持访问序列化.因此,如果 100 个线程有一个 db 实例,则对实际磁盘数据库的调用将被序列化.

So, one helper instance, one db connection. Even if you use it from multiple threads, one connection at a time. The SqliteDatabase object uses java locks to keep access serialized. So, if 100 threads have one db instance, calls to the actual on-disk database are serialized.

所以,一个helper,一个db connection,用java代码序列化.一个线程,1000个线程,如果你使用它们之间共享的一个辅助实例,那么你所有的数据库访问代码都是串行的.生活很好(ish).

So, one helper, one db connection, which is serialized in java code. One thread, 1000 threads, if you use one helper instance shared between them, all of your db access code is serial. And life is good (ish).

如果您尝试同时从实际的不同连接写入数据库,则会失败.它不会等到第一个完成再写.它根本不会写入您的更改.更糟糕的是,如果你没有在 SQLiteDatabase 上调用正确版本的插入/更新,你将不会得到异常.您只会在 LogCat 中收到一条消息,仅此而已.

If you try to write to the database from actual distinct connections at the same time, one will fail. It will not wait till the first is done and then write. It will simply not write your change. Worse, if you don’t call the right version of insert/update on the SQLiteDatabase, you won’t get an exception. You’ll just get a message in your LogCat, and that will be it.

那么,多线程?使用一名助手.时期.如果您知道只有一个线程正在写入,您可以使用多个连接,并且您的读取速度会更快,但买家要小心.我还没有测试那么多.

So, multiple threads? Use one helper. Period. If you KNOW only one thread will be writing, you MAY be able to use multiple connections, and your reads will be faster, but buyer beware. I haven't tested that much.

这是一篇包含更多细节和示例应用的博客文章.

Here's a blog post with far more detail and an example app.

  • Android Sqlite Locking (Updated link 6/18/2012)
  • Android-Database-Locking-Collisions-Example by touchlab on GitHub

Gray 和我实际上正在基于他的 Ormlite 开发一个 ORM 工具,该工具在本机与 Android 数据库实现一起工作,并遵循我在博客文章中描述的安全创建/调用结构.那应该很快就出来了.看看.

Gray and I are actually wrapping up an ORM tool, based off of his Ormlite, that works natively with Android database implementations, and follows the safe creation/calling structure I describe in the blog post. That should be out very soon. Take a look.

与此同时,有一篇后续博客文章:

In the meantime, there is a follow up blog post:

还要检查前面提到的锁定示例的 2point0 的分叉:

Also checkout the fork by 2point0 of the previously mentioned locking example:

  • Android-Database-Locking-Collisions-Example by 2point0 on GitHub

这篇关于在 Android 上使用 SQLite 时如何避免并发问题?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆