我需要从数据库中读取一些数据,同时我在一个事务的另一个线程中加载一些数据。
我的所有读取其他表的线程都会停止,直到其他线程中的事务完成为止。
我需要能够从数据库中读取信息而不必担心其他线程。
我已经阅读了很多关于sqlite,android的信息...但是没有任何工作,总是我的查询参数被阻止。
我已经遵循了这个建议,因为@KevinGalligan在这个帖子(What are the best practices for SQLite on Android?)中解决了锁定和其他问题。
1)我只使用一个SQLiteOpenHelper(单例)
2)我从不关闭数据库
我试过了:
用以下方式开始交易:
database.execSQL("begin immediate transaction");
或
database.beginTransactionNonExclusive();
代替
database.beginTransaction();
无效,查询已被屏蔽。
我已经读过WAL(database.enableWriteAheadLogging()),但我需要支持api 9.
同时阅读任何其他解决方案的事务正在更新某些表吗?如果我的信息被弃用,我不在乎,不要阻止我的线程更重要。
答案 0 :(得分:6)
我解决了这个问题。
我按照这个步骤。
解决数据库锁定和多线程使用数据库的问题(基于http://touchlabblog.tumblr.com/post/24474750219/single-sqlite-connection):
1)我只使用一个SQLiteOpenHelper(单例)。
2)永远不要关闭数据库。
为了能够在不阻止查询的情况下进行读写,我按照以下步骤操作:
使用database.enableWriteAheadLogging()
(仅限api> = 11),我的错误是您必须在所有连接中启用此模式,不仅在您的交易或您的作品中,所以我将以下代码添加到我的openHelper类in" onOpen"方法。基于此github中的Mozilla代码(https://github.com/mozilla/mozilla-central/blob/9f2b8297b99d9d28038256b4f92a5aaa941749f1/mobile/android/base/db/TabsProvider.java)。
@SuppressLint("NewApi")
@Override
public void onOpen(SQLiteDatabase db) {
// From Honeycomb on, it's possible to run several db
// commands in parallel using multiple connections.
if (Build.VERSION.SDK_INT >= 11) {
try{
db.enableWriteAheadLogging();
}catch(Exception e){
Log.e("onOpen", e.getMessage());
}
}
}
使用此解决方案,我解决了在更新某些表时阻止读取的问题,但其他更新也被阻止了。如果你想解决这个问题,正如@commonsware所说:
在事务中使用yieldIfContendedSafely()
,您将为其他线程提供使用数据库的机会。我没有看到使用此方法与beginTransaction
或。{
beginTransactionNonExclusive
。
另一个有趣的读物是:What are the best practices for SQLite on Android?
答案 1 :(得分:2)
我认为您应该使用同步概念来避免您遇到的问题。
答案 2 :(得分:2)
如果您的数据加载工作不只是一个大规模的SQL事务,use yieldIfContendedSafely()
允许您的其他线程在不同的点读取数据库。因此,例如,如果您正在进行某种批量数据加载,并且每100个插入执行一次事务,请在每100次插入循环的每次传递中调用yieldIfContendedSafely()
,以便为其他线程提供机会使用数据库。
答案 3 :(得分:0)
android中的SQLite不是线程安全的,数据库将在执行操作时被锁定,这意味着你应该确保数据库操作只在一个线程中执行,并调用database.setTransactionSuccessful();在你的工作完成后结束交易。
答案 4 :(得分:0)
我建议在方向上关闭同步SQLITE选项(默认情况下,在Android中,当一个写入事务操作正在运行时,其他读取数据库查询正在等待完成写入事务)
您应该在每次连接到该选项的数据库类型之前,通过
\0
结果,所有读取操作将立即执行,但是您会从数据库中获取一些过时的数据(您无法在结果数据中看到正在运行的写事务正在插入到数据库中)