记一次本地数据库迁移

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/heming9174/article/details/82993745

记一次本地数据库迁移

  • 需求原因:

    • 因APP存在无网络使用场景,所以无法通过网络接口请求处理,需要本地存在大量数据(>20W条).
    • 相关数据存在 公司隐私,敏感等问题,数据库无法全部内置在assets内.原有方法是:第一次进入由 网点/中心使用人员 连接网络,放置,等待下载完成.
    • 因考虑全国各地网络情况,时间等因素,现将 不涉及隐私的 车牌信息(18W+)数据,放置在安装包assets内,在第一次进入APP时,进行迁移,迁移到data/data/packageName/database内.同时再创建其他表和下载其他数据,以节省时间和提高易用性.

  • 解决办法.

    • 第一个想到的办法就是,再创建一个数据库,同时连接2个数据库,assets数据库 读取-> 写入 database数据库.还是很麻烦,PASS ! .
    • 将Application初始化数据库相关操作延后,开启工作线程对整个数据库进行迁移,完成后删除,再创建其他表和索引.
      1. 使用APP下载全部数据,导出,Navicat SQLite打开,删除其他表数据,保留非敏感数据.
      2. 需要额外考虑的是:迁移数据库失败,该表信息就缺失.需要在创建表,额外创建,使用CREATE TABLE IF NOT EXISTS tabname避免重复创建,
      3. 迁移完成后,对原有assets内数据进行删除
      4. 正常database初始化,创建表/索引,更新操作(多年老项目,沿用原生SQLite,存在大量数据库版本更新).
  • 遇到的问题

    1. 打开APP,直接Crash了,查看logcat,提示数据库版本不能进行降级.
      (WTF…我明明是拿同一个数据库进行操作,并没有进行升级操作.)

      解决办法:

      PRAGMA user_version

      查看需要迁移的数据库版本,发现版本号果然比代码内数据库版本高1.

      PRAGMA user_version=?

      ?表示你需要设置的数据库版本号.

    2. 迁移数据库版本号改为0,下载数据中出现ANR

      adb pull data/trace导出ANR文件信息,发现是VMThread.wait()等待同步锁的释放导致ANR,查看代码,发现是由于未执行更新数据库操作,没有及时更新索引,导致查询超时.

      解决办法:

      查看SQLiteOpenHeler源码,发现在初始化数据库时,调用构造函数,传入4个参数 context,name,factory,version,再调用getReadableDatabase() 后调用 getDatabaseLocked() 函数内有相关逻辑处理,因 version==0.直接执行 **onCreate()**方法没有执行更新数据库的操作导致.
      SQLiteOpenHelper


最终解决方案

通过 PRAGMA user_version=1将需要迁移的数据库版本改为1,将创建其他表结构/新增索引等操作放
在 **onUpgrade()**内执行.

最终能够保证 数据迁移后,维持原有数据库表结构,数据库正常的更新升级.


Tips:

踩坑途中遇到这个异常.

java.lang.IllegalStateException: Cannot perform this operation because there is no current transaction

strackoverflow上面没有找到满意的答案,最后断点调试,发现异常原因是: SQL的语法问题

猜你喜欢

转载自blog.csdn.net/heming9174/article/details/82993745