在onCreate时初始化SQLite遇SQLITE_BUSY错误,求代码排查
解决SQLite onCreate中SQLITE_BUSY(数据库锁定)问题
我来帮你排查这个SQLITE_BUSY的问题——你遇到的数据库锁定错误,根源出在对SQLiteOpenHelper的数据库实例管理逻辑上。
先看你的代码:
private SQLiteDatabase DefaultWritableDatabase = null; private static final String DATABASE_NAME = "arrived.db"; private static final int DATABASE_VERSION = 3; @Override public SQLiteDatabase getWritableDatabase() { final SQLiteDatabase db; if (DefaultWritableDatabase != null) { db = DefaultWritableDatabase; } else { db = super.getWritableDatabase(); } return db; } @Override public void onCreate(SQLiteDatabase db) { this.DefaultWritableDatabase = db; // Create table String Create_Query = "CREATE TABLE IF NOT EXISTS arrivedservice (" + "_id INTEGER PRIMARY KEY AUTOINCREMENT, " + "Lat TEXT ," + "Lon TEXT , " + "LeaveTime INTEGER " + ");"; db.execSQL(Create_Query); //Give initial value to the Sqlite when onCreate String LeaveTime = String.valueOf(System.currentTimeMillis()); String Insert_Query = "INSERT INTO arrivedservice (_id,Lat,Lon,LeaveTime) VALUES ('1','240.22652','151.523978'," + LeaveTime + ")"; db.execSQL(Insert_Query); }
问题分析
- 错误的数据库实例持有逻辑:你重写了
getWritableDatabase(),并在onCreate中将传入的db实例保存为全局变量,后续强制返回这个实例。但SQLiteOpenHelper本身会负责数据库连接的创建、复用和关闭,你强行持有这个实例会破坏它的内部管理机制,导致连接冲突。 - onCreate期间的锁定冲突:当
onCreate执行时,SQLiteOpenHelper已经打开了数据库连接并处于操作状态,此时你持有这个实例并在后续复用,容易造成数据库被当前操作锁定,触发SQLITE_BUSY错误。
修复方案
去掉自定义的getWritableDatabase()重写,也不需要全局保存数据库实例。让SQLiteOpenHelper自行管理连接,onCreate中直接使用传入的db参数完成操作即可:
private static final String DATABASE_NAME = "arrived.db"; private static final int DATABASE_VERSION = 3; @Override public void onCreate(SQLiteDatabase db) { // Create table String Create_Query = "CREATE TABLE IF NOT EXISTS arrivedservice (" + "_id INTEGER PRIMARY KEY AUTOINCREMENT, " + "Lat TEXT ," + "Lon TEXT , " + "LeaveTime INTEGER " + ");"; db.execSQL(Create_Query); // 初始化插入数据(建议去掉手动指定的_id,让自增主键自动生成) String LeaveTime = String.valueOf(System.currentTimeMillis()); // 因为_id是自增主键,不需要手动插入值,数据库会自动生成 String Insert_Query = "INSERT INTO arrivedservice (Lat,Lon,LeaveTime) VALUES ('240.22652','151.523978'," + LeaveTime + ")"; db.execSQL(Insert_Query); } // 如需获取数据库实例,直接调用父类方法即可,不需要重写 // public SQLiteDatabase getWritableDatabase() { // return super.getWritableDatabase(); // }
额外建议
- 你的
_id是自增主键,手动指定'1'虽然可以工作,但不符合自增主键的设计逻辑,建议去掉该字段的插入值,让数据库自动生成主键ID,避免后续插入时可能出现的主键冲突。 - 不要长期持有SQLiteDatabase实例,每次操作完成后可以调用
close()关闭(或者依赖SQLiteOpenHelper的管理,在合适的时机关闭),减少数据库锁定的概率。
内容的提问来源于stack exchange,提问作者Kliff
相关产品推荐
相关产品推荐

