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

使用Golang操作SQLite时触发Database Locked Error(错误码5)

SQLite Database Locked Error(错误码5)排查方案

问题背景

执行代码时,在tx.Commit()步骤触发Database Locked Error(错误码5),此前同类代码未出现该异常。

相关代码实现

UserRepository 代码

type UserRepository struct {
    db *driver.QuestionlyDb
}

/*
Creates a new user sql driver that executes user sql statements on the sql driver.
*/
func CreateUserRepository(db *driver.QuestionlyDb) *UserRepository {
    return &UserRepository{db: db}
}

/*
Create a new user row in the database.
*/
func (ur *UserRepository) CreateUser(u *User) error {
    tx, err := ur.db.Begin()
    if err != nil {
        return err
    }

    stmt, err := tx.Prepare(`INSERT INTO users (id, email, password, username) VALUES (?, ?, ?, ?);`)
    if err != nil {
        _ = tx.Rollback()
        return err
    }

    defer stmt.Close()

    _, err = stmt.Exec(u.GetID(), u.GetEmail(), u.GetPassword(), u.GetUsername())
    if err != nil {
        tx.Rollback()
        return err
    }

    if err := tx.Commit(); err != nil {
        return err
    }

    return nil
}

数据库连接代码

type QuestionlyDb struct {
    *sql.DB
}

/*
Creates a new database connection.
*/
func CreateDatabase() (*QuestionlyDb, error) {
    db, err := connectToDb()
    if err != nil {
        return nil, err
    }
    sqlDb := &QuestionlyDb{db}
    return sqlDb, nil
}

// TODO: Set db name as env variable
func connectToDb() (*sql.DB, error) {
    db, err := sql.Open("sqlite3", "./questionly.db")
    if err != nil {
        return nil, err
    }
    return db, err
}

排查与解决方法

  • 检查未释放的连接/事务:SQLite是单写数据库,若有其他进程(如数据库管理工具)或代码持有未关闭的连接、未提交/回滚的事务,会导致锁阻塞。关闭所有访问该数据库的外部工具,确保所有事务都执行了Commit()或Rollback()。
  • 配置连接池参数:SQLite不支持并发写,需限制连接池大小,避免多连接竞争锁。修改connectToDb()函数:
    func connectToDb() (*sql.DB, error) {
        db, err := sql.Open("sqlite3", "./questionly.db")
        if err != nil {
            return nil, err
        }
        // 添加连接池配置
        db.SetMaxOpenConns(1)
        db.SetMaxIdleConns(1)
        db.SetConnMaxLifetime(0)
        return db, err
    }
    
  • 优化事务内资源释放:虽然不是核心原因,但可提前关闭语句对象,避免资源占用。修改CreateUser中的错误处理逻辑:
    _, err = stmt.Exec(u.GetID(), u.GetEmail(), u.GetPassword(), u.GetUsername())
    if err != nil {
        _ = stmt.Close() // 提前关闭语句
        _ = tx.Rollback()
        return err
    }
    
  • 验证文件权限:确认questionly.db所在目录及文件有进程读写权限,权限不足可能导致锁操作失败。

内容的提问来源于stack exchange,提问作者Milan Medić

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 12:09:20