内容提供者和内容观察者同步
我正在运行一个服务,其中包含一个 SQLite DB 和一个注册到该 DB 的 URI 的内容观察器。 Content Observer 使用 SQLiteOpenHelper 从数据库查询数据。因此,当新数据通过内容提供商从其他应用程序放入服务数据库时,将观察更改的游标并查询要处理的数据。问题是,如果我从其他应用程序快速插入数据,最终内容观察者和内容提供者都会打开数据库,并导致 SQLite 错误和数据库锁定。
我正在使用 getReadable 和 getWritable 方法,并在使用后关闭数据库和任何游标。看来CP和CO不同步。我该如何解决这个问题?
更新 当我在摩托罗拉 Atrix 上测试时,没有任何问题。当我在 Samsung Galaxy Tab 上测试它时,我遇到了问题。在 Atrix 上,从目录中的调试标签看来,CO 和 CP 同时打开了 DB...但仍然不像 Galaxy 那样存在问题。 Galaxy 给我这个错误:
11-04 12:12:13.490: ERROR/SqliteDatabaseCpp(19978): sqlite3_open_v2("/data/data/my.package/databases/raw_data_buffer.db", &handle, 6, NULL) failed
11-04 12:12:13.490: ERROR/SQLiteDatabase(19978): Failed to open the database. closing it.
11-04 12:12:13.490: ERROR/SQLiteDatabase(19978): android.database.sqlite.SQLiteDatabaseLockedException: database is locked
11-04 12:12:13.490: ERROR/SQLiteDatabase(19978): at android.database.sqlite.SQLiteDatabase.dbopen(Native Method)
11-04 12:12:13.490: ERROR/SQLiteDatabase(19978): at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:983)
11-04 12:12:13.490: ERROR/SQLiteDatabase(19978): at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:956)
11-04 12:12:13.490: ERROR/SQLiteDatabase(19978): at android.database.sqlite.SQLiteDatabase.openOrCreateDatabase(SQLiteDatabase.java:1021)
11-04 12:12:13.490: ERROR/SQLiteDatabase(19978): at android.app.ContextImpl.openOrCreateDatabase(ContextImpl.java:750)
11-04 12:12:13.490: ERROR/SQLiteDatabase(19978): at android.content.ContextWrapper.openOrCreateDatabase(ContextWrapper.java:221)
11-04 12:12:13.490: ERROR/SQLiteDatabase(19978): at android.database.sqlite.SQLiteOpenHelper.getWritableDatabase(SQLiteOpenHelper.java:149)
11-04 12:12:13.490: ERROR/SQLiteDatabase(19978): at my.package.RawDataBufferDatabaseHelper.insert(RawDataBufferDatabaseHelper.java:93)
11-04 12:12:13.490: ERROR/SQLiteDatabase(19978): at my.package.NetService$NetworkPollingRunnable.run(NetService.java:166)
11-04 12:12:13.490: ERROR/SQLiteDatabase(19978): at java.lang.Thread.run(Thread.java:1020)
11-04 12:12:13.490: WARN/dalvikvm(19978): threadid=9: thread exiting with uncaught exception (group=0x40189760)
11-04 12:12:13.490: ERROR/AndroidRuntime(19978): FATAL EXCEPTION: Thread-14
11-04 12:12:13.490: ERROR/AndroidRuntime(19978): android.database.sqlite.SQLiteDatabaseLockedException: database is locked
11-04 12:12:13.490: ERROR/AndroidRuntime(19978): at android.database.sqlite.SQLiteDatabase.dbopen(Native Method)
11-04 12:12:13.490: ERROR/AndroidRuntime(19978): at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:983)
11-04 12:12:13.490: ERROR/AndroidRuntime(19978): at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:956)
11-04 12:12:13.490: ERROR/AndroidRuntime(19978): at android.database.sqlite.SQLiteDatabase.openOrCreateDatabase(SQLiteDatabase.java:1021)
11-04 12:12:13.490: ERROR/AndroidRuntime(19978): at android.app.ContextImpl.openOrCreateDatabase(ContextImpl.java:750)
11-04 12:12:13.490: ERROR/AndroidRuntime(19978): at android.content.ContextWrapper.openOrCreateDatabase(ContextWrapper.java:221)
11-04 12:12:13.490: ERROR/AndroidRuntime(19978): at android.database.sqlite.SQLiteOpenHelper.getWritableDatabase(SQLiteOpenHelper.java:149)
11-04 12:12:13.490: ERROR/AndroidRuntime(19978): at my.package.RawDataBufferDatabaseHelper.insert(RawDataBufferDatabaseHelper.java:93)
I have a service running that contains an SQLite DB and a Content Observer registered to the DB's URI. The Content Observer uses an SQLiteOpenHelper to query the data from the DB. So when new data is put into the services DB from other application via Content Provider the changed cursor will be observed and query the data to process. The problem is if I insert data at a fast pace from other applications I end up with both the Content Observer and Content Provider opening the DB and causes an SQLite error with a database lock.
I am using the getReadable and getWritable methods and closing the DB and any cursors after they are used. It just seem that the CP and CO are not in sync. How can I fix this problem?
UPDATE
When I test this on a Motorola Atrix I have no problems. When I test it on a Samsung Galaxy Tab I get problems. On the Atrix it appears from my debug tags in the catlog that both the CO and the CP have the DB open at the same time... but still not problem like there is with the Galaxy. The Galaxy gives me this error:
11-04 12:12:13.490: ERROR/SqliteDatabaseCpp(19978): sqlite3_open_v2("/data/data/my.package/databases/raw_data_buffer.db", &handle, 6, NULL) failed
11-04 12:12:13.490: ERROR/SQLiteDatabase(19978): Failed to open the database. closing it.
11-04 12:12:13.490: ERROR/SQLiteDatabase(19978): android.database.sqlite.SQLiteDatabaseLockedException: database is locked
11-04 12:12:13.490: ERROR/SQLiteDatabase(19978): at android.database.sqlite.SQLiteDatabase.dbopen(Native Method)
11-04 12:12:13.490: ERROR/SQLiteDatabase(19978): at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:983)
11-04 12:12:13.490: ERROR/SQLiteDatabase(19978): at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:956)
11-04 12:12:13.490: ERROR/SQLiteDatabase(19978): at android.database.sqlite.SQLiteDatabase.openOrCreateDatabase(SQLiteDatabase.java:1021)
11-04 12:12:13.490: ERROR/SQLiteDatabase(19978): at android.app.ContextImpl.openOrCreateDatabase(ContextImpl.java:750)
11-04 12:12:13.490: ERROR/SQLiteDatabase(19978): at android.content.ContextWrapper.openOrCreateDatabase(ContextWrapper.java:221)
11-04 12:12:13.490: ERROR/SQLiteDatabase(19978): at android.database.sqlite.SQLiteOpenHelper.getWritableDatabase(SQLiteOpenHelper.java:149)
11-04 12:12:13.490: ERROR/SQLiteDatabase(19978): at my.package.RawDataBufferDatabaseHelper.insert(RawDataBufferDatabaseHelper.java:93)
11-04 12:12:13.490: ERROR/SQLiteDatabase(19978): at my.package.NetService$NetworkPollingRunnable.run(NetService.java:166)
11-04 12:12:13.490: ERROR/SQLiteDatabase(19978): at java.lang.Thread.run(Thread.java:1020)
11-04 12:12:13.490: WARN/dalvikvm(19978): threadid=9: thread exiting with uncaught exception (group=0x40189760)
11-04 12:12:13.490: ERROR/AndroidRuntime(19978): FATAL EXCEPTION: Thread-14
11-04 12:12:13.490: ERROR/AndroidRuntime(19978): android.database.sqlite.SQLiteDatabaseLockedException: database is locked
11-04 12:12:13.490: ERROR/AndroidRuntime(19978): at android.database.sqlite.SQLiteDatabase.dbopen(Native Method)
11-04 12:12:13.490: ERROR/AndroidRuntime(19978): at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:983)
11-04 12:12:13.490: ERROR/AndroidRuntime(19978): at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:956)
11-04 12:12:13.490: ERROR/AndroidRuntime(19978): at android.database.sqlite.SQLiteDatabase.openOrCreateDatabase(SQLiteDatabase.java:1021)
11-04 12:12:13.490: ERROR/AndroidRuntime(19978): at android.app.ContextImpl.openOrCreateDatabase(ContextImpl.java:750)
11-04 12:12:13.490: ERROR/AndroidRuntime(19978): at android.content.ContextWrapper.openOrCreateDatabase(ContextWrapper.java:221)
11-04 12:12:13.490: ERROR/AndroidRuntime(19978): at android.database.sqlite.SQLiteOpenHelper.getWritableDatabase(SQLiteOpenHelper.java:149)
11-04 12:12:13.490: ERROR/AndroidRuntime(19978): at my.package.RawDataBufferDatabaseHelper.insert(RawDataBufferDatabaseHelper.java:93)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
在这种情况下,关闭游标实际上不会对任何事情产生任何影响。不要让您的 CO 直接访问数据库。让您的每一段代码都通过 ContentProvider,并且在您的内容提供程序中仅打开一个可写连接和一个可读连接(创建这些实例变量)。这应该保持一切一致,因为这样你将只有一个正在经历的数据库连接。只要您使用相同的数据库连接就可以了。 sqlite 方法是可重入的。
Closing the cursors really doesn't have any affect on anything in this case. Don't have your CO's directly accessing the database. Make every piece of your code go through the ContentProvider and in your content provider only have one writeable and one readable connection open (make these instance variables). That should keep everything consistent because then you'll only have one db connection that you're going through. As long as you're using the same db connection you're fine. The sqlite methods are reentrant.