You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

问题分析

  1. 错误的数据库实例持有逻辑:你重写了getWritableDatabase(),并在onCreate中将传入的db实例保存为全局变量,后续强制返回这个实例。但SQLiteOpenHelper本身会负责数据库连接的创建、复用和关闭,你强行持有这个实例会破坏它的内部管理机制,导致连接冲突。
  2. 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 06:34:10