在事务运行时读取sqlite数据(Android)

我需要从数据库读取一些数据,同时我在一个事务的另一个线程中加载一些数据。

读取其他表的所有线程都将停止,直到其他线程中的事务完成。

我需要能够从数据库中读取信息而不必担心其他线程。

我已经阅读了很多关于sqlite,android的信息…但是没有什么工作,总是我的查询参数被阻止。

我遵循这个建议,因为@KevinGalligan在这个post中说( Android上SQLite的最佳做法是什么? )解决锁和其他问题。

1)我只使用一个SQLiteOpenHelper(单例)

2)我从未关闭数据库

我试过了:

用以下内容开始交易:

database.execSQL("begin immediate transaction"); 

要么

 database.beginTransactionNonExclusive(); 

代替

 database.beginTransaction(); 

不工作,查询被阻止。

我已经读过WAL(database.enableWriteAheadLogging()),但我需要支持api 9。

同时读取事务的任何其他解决方案是更新某些表吗? 我不在乎我的信息是否被弃用,更重要的是不要阻止我的线程。

我解决了这个问题。

我按照这个步骤。

解决数据库锁定和multithreading使用数据库的问题(基于http://touchlabblog.tumblr.com/post/24474750219/single-sqlite-connection ):

1)我只使用一个SQLiteOpenHelper(单例)。

2)永远不要关闭数据库。

为了能够在不阻止我的查询的情况下进行读写,我按照以下步骤操作:

使用database.enableWriteAheadLogging() (只有api> = 11),我的错误是您必须在所有连接中启用此模式,不仅仅是在您的事务或您的着作中,所以我在“onOpen”中将以下代码添加到我的openHelper类中“ 方法。 基于此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() ,您将为其他线程提供使用数据库的机会。 我没有看到使用此方法与beginTransactionbeginTransactionNonExclusive有任何区别。

另一个有趣的读物是: Android上SQLite的最佳实践是什么?

我认为您应该使用同步概念来避免您遇到的问题。

android中的SQLite不是线程安全的,数据库将在执行操作时被锁定,这意味着你应该确保数据库操作只在一个线程中执行,并调用database.setTransactionSuccessful(); 完成工作后结束交易。

如果您的数据加载工作不仅仅是一个大规模的SQL事务,请使用yieldIfContendedSafely()来允许您的其他线程在不同的点读取数据库。 因此,例如,如果您正在进行某种批量数据加载,并且每100个插入执行一次事务,则在每100次插入循环的每次传递中调用yieldIfContendedSafely() ,以使您的其他线程有机会工作与数据库。