Android中的SQLiteDiskIOException

时间:2010-07-10 19:08:30

标签: android

我们的Android应用中出现了大量SQLiteDiskIOException错误,堆栈跟踪类似于以下内容:

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)

这是几周前最近开始发生的事情,但在此问题的报告开始的确切版本中没有发生重大的数据库更改。尽管有(我相信)适当的索引,但是在查询完成后,我们对cursor.moveToFirst()调用感到满意,但是从堆栈跟踪中可以看到这个异常。到目前为止,我们完全无法重现。

查询有点复杂,有三个左连接。下面是一个代表性查询,更改了一些标识列以保护无辜者。

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

其他消息来源表示我们正试图提取太多数据,但事实并非如此。我们能够获得完整数据库行计数的三个用户案例显示: cse与< 2000条目, 以< 150条目为准,并且 预先输入0或7个条目。 此外,查询中的“解释查询计划”表示所有联接都是针对索引列完成的。

在每种情况下我们都看到过,用户在各种设备上运行Android 2.1(DROID,Hero,EVO,可能还有其他设备)。值得注意的是,我们还没有在我们拥有的G1设备上看到这一点,即使它们与其他应用程序一起被加载。

最后,卸载和重新安装已成功地解决了问题,但可能只是暂时的。

我担心此问题是Android 2.1中数据损坏的结果。 有没有人有可能的建议来研究什么? 这可能与this Android bug on SQLiteDatabaseCorruptException

有关

非常感谢指导和解决方案。

3 个答案:

答案 0 :(得分:7)

似乎你有多线程问题,一个线程试图获取数据而另一个或多个尝试将一些数据插入到表中,因为异常是从方法(getCount)抛出的。

也别忘了; SQLite游标未在内部同步,因此如果您从多个线程使用此游标,则应执行自己的同步机制。

答案 1 :(得分:1)

我们有类似的问题。当我们的应用程序启动时发生souch错误。 在onCreate方法中,我们检查应用程序路径中是否有任何数据库。如果发生任何数据库,我们调用此类代码

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;
    }

如果没有数据库(首次运行应用程序),我们会从资源中复制它。 但有时会发生SQLiteDiskIOException和来自资源的数据库调用。

答案 2 :(得分:0)

一个原因是Bassel Kh说,多线程问题,另一个原因是数据库不可用,即。 db被删除或sdcard不可用。