SQLiteDiskIOException in Android
We are getting a large number of SQLiteDiskIOException
errors in our Android app, with stack traces similar to the following:
E/AndroidRuntime( 2252): Caused by: android.database.sqlite.SQLiteDiskIOException: disk I/O error
E/AndroidRuntime( 2252): at android.database.sqlite.SQLiteQuery.native_fill_window(Native Method)
E/AndroidRuntime( 2252): at android.database.sqlite.SQLiteQuery.fillWindow(SQLiteQuery.java:75)
E/AndroidRuntime( 2252): at android.database.sqlite.SQLiteCursor.fillWindow(SQLiteCursor.java:288)
E/AndroidRuntime( 2252): at android.database.sqlite.SQLiteCursor.getCount(SQLiteCursor.java:269)
E/AndroidRuntime( 2252): at android.database.AbstractCursor.moveToPosition(AbstractCursor.java:171)
E/AndroidRuntime( 2252): at android.database.AbstractCursor.moveToFirst(AbstractCursor.java:248)
E/AndroidRuntime( 2252): at com.company.android.CActivity$QueryTask.doInBackground(CActivity.java:1660)
This recently starting happening a few weeks ago, but no significant database changes took place in the exact release in which reporting of this issue started. Despite having (I believe) appropriate indices, this exception has been reported more than we are comfortable with on cursor.moveToFirst()
calls after the query completes, as you can see from the stack trace. So far, we have been completely unable to reproduce.
The query is somewhat complicated, with three left joins. Below is a representative query, with some identifying columns changed to protect the innocent.
select distinct c._id as _id,c.type as type,c.name as name,c.slug as slug,c.description as description,c.extra1 as extra1,c.extra2 as extra2,c.extra3 as extra3,c.extra4 as extra4,c.extra5,c.extra6 as extra6,c.extra7 as extra7,c.extra8 as extra8, c.extra9 as extra9,c.sslug as sslug,
c2.name as sname,
p.type as prel,
em.dS as dS,em.eS as eS
from cse as c
left join cse as c2 on c.sslug=c2.slug
left join emed as em on c.slug=em.slug
left join pre as p on c.sslug=p.slug
where c.pslug='slug' AND c.user='user' AND c.csource='csource'
order by c.type asc, c.extra6 desc, c.sortorder asc
Other sources have suggested that we are trying to pull out too much data, but this is simply not the c开发者_开发知识库ase. The three user cases where we have been able to get full database rowcounts show: cse with < 2000 entries, emed with <150 entries, and pre with either 0 or 7 entries. Furthermore 'explain query plan' on the query indicates all joins are done against indexed columns.
In every case we have seen this, the user was running Android 2.1 on a variety of devices (DROID, Hero, EVO, possibly others). Notably, we have not seen this on a couple G1 devices we have, even when they are loaded down with other apps.
Finally, uninstalling and reinstalling has proven successful in cleaning up the issue, though possibly only temporarily.
I fear this problem is a result of data corruption in Android 2.1. Does anyone have possible suggestions of what to look into? Could this be related to this Android bug on SQLiteDatabaseCorruptException
Guidance and solutions are much appreciated.
It seems that you have multi threading issue, one thread tries to get the data while another one or more than one are trying to insert some data into your tables,because the exception is thrown from method (getCount).
Also don't forget; SQLite cursor is not internally synchronized, so if you use this cursor from multiple threads you should perform your own sync mechanism.
We have similar problem. When our application starts souch error occurs. In onCreate method we check is there any database in application path. If any database occurs, we invoke such code
public boolean createDataBase() throws IOException
{
boolean dbExist = checkDataBase();
if(dbExist)
{
//do nothing - database already exist
}
else
{
//By calling this method and empty database will be created into the default system path
//of your application so we are gonna be able to overwrite that database with our database.
this.getReadableDatabase();
}
return dbExist;
}
private boolean checkDataBase()
{
SQLiteDatabase checkDB = null;
try
{
String myPath = DATABASE_PATH + DATABASE_NAME;
checkDB = SQLiteDatabase.openDatabase(myPath, null, SQLiteDatabase.OPEN_READONLY);
}
catch(SQLiteException e)
{
}
if(checkDB != null)
{
checkDB.close();
}
return checkDB != null ? true : false;
}
And if there is no database(first run of application) we copy it from resources. But some times occurs SQLiteDiskIOException and database calls from resources.
one reason is as Bassel Kh stated, multi thread problom, the another is the db is unavailable, ie. db is deleted or sdcard is unavaliable.
精彩评论