当前位置: 首页 > news >正文

SQLite 写入锁表报错 database is locked 怎么排查解决

遇到 SQLite 报 database is locked,通常是写操作被阻塞,最直接的解决办法是检查是否有未提交的事务,并在高并发场景下开启 WAL 模式。

先说结论:这个问题多数是因为写锁冲突,优先检查长事务和并发写入策略

  • 先确认:是否有进程独占数据库文件或事务未提交
  • 先处理:开启 WAL 模式并设置合理的 busy_timeout
  • 再验证:重新执行写入操作并监控日志

命令速用版

如果是命令行环境或支持 PRAGMA 的工具,可以尝试以下设置来缓解锁等待:

PRAGMA journal_mode=WAL;
PRAGMA busy_timeout=5000;

第一行开启预写日志模式,第二行设置锁等待超时时间为 5000 毫秒。注意这些设置针对当前连接生效,持久化配置需写入数据库文件或应用初始化代码中。

为什么会这样

SQLite 默认使用回滚日志(Rollback Journal),在进行写操作时需要对数据库文件加独占锁。如果另一个连接正在写入,或者有一个读事务未结束(在某些隔离级别下),新的写请求就会拿不到锁。

当应用层没有正确处理事务提交,或者多个进程同时尝试写入同一个文件时,SQLite 会返回 SQLITE_BUSY 错误,上层驱动通常将其映射为 database is locked。此外,如果数据库文件位于不支持文件锁的网络文件系统(如 NFS)上,锁机制也会失效或行为异常。

分步处理

1. 检查未提交的事务

查看应用日志,确认是否有长时间运行的事务没有 commit 或 rollback。在代码中确保每个写操作都在 try-catch-finally 块中正确关闭事务。

2. 开启 WAL 模式

在数据库初始化时执行:

PRAGMA journal_mode=WAL;

WAL 模式允许读操作和写操作并发进行,减少写锁阻塞读的情况,也能改善部分写并发场景。执行后可通过 PRAGMA journal_mode; 确认是否返回 wal。

3. 设置忙等待超时

在连接建立后设置:

PRAGMA busy_timeout=5000;

这会让 SQLite 在遇到锁时等待指定毫秒数,而不是立即报错。数值需要根据业务容忍度调整,公开资料中没有看到可靠的量化数据表明具体多少毫秒最佳,通常建议从 3000 到 10000 之间尝试。

4. 检查文件系统

确认数据库文件不在 NFS、CIFS 等网络共享存储上。SQLite 官方文档明确指出本地文件系统之外的锁行为可能不可靠。如果必须在共享存储使用,需评估锁文件机制是否兼容。

怎么验证是否生效

1. 重新执行之前报错的写入操作,观察是否不再抛出异常。

2. 在高并发测试下,监控应用日志中 database is locked 出现的频率是否下降。

3. 使用 lsof | grep .sqlite 或类似命令查看数据库文件是否被异常进程长时间占用。

常见坑

1. PRAGMA 作用域:PRAGMA 设置通常只对当前数据库连接生效,重启连接后可能失效,需确保在每次建立连接时初始化配置。

2. 多进程写入:SQLite 适合读多写少,如果多个进程频繁同时写入,即使开启 WAL 也会 serialized(串行化),性能会下降,这不是锁报错但需注意。

3. 备份锁死:某些备份工具在复制数据库文件时会加锁,导致业务写入失败,备份前建议先 vacuum 或使用 SQLite 在线备份 API。

参考来源

  • SQLite 官方文档 - Locking And Concurrency In SQLite: https://www.sqlite.org/lockingv3.html
  • SQLite 官方文档 - Write-Ahead Logging: https://www.sqlite.org/wal.html
  • SQLite 官方文档 - PRAGMA busy_timeout: https://www.sqlite.org/pragma.html#pragma_busy_timeout

原文链接:https://www.zjcp.cc/ask/10828.html

http://www.jsqmd.com/news/795896/

相关文章:

  • STK Target Sequence实战:不写一行代码,30分钟搞定卫星初始轨道参数优化
  • 高点摄像山火烟雾检测数据集(并按照低、中详细标注烟雾浓度)。主要针对初期山火,任何野火检测系统的最重要目标是在火势扩大之前及时检测到火灾
  • NoFences:免费开源桌面分区工具,5分钟打造高效整洁工作空间
  • 终极D2DX指南:让经典暗黑破坏神2在现代电脑上焕发新生
  • 从仿真到流片:手把手教你搞定BJT温度传感器中的A、B值计算与校准
  • 告别同义词替换!我实测了3款降AI工具,英文论文稳过Turnitin检测
  • 保姆级教程:在Ubuntu 20.04上从零编译运行ORB-SLAM3(含Pangolin报错解决)
  • Vue2和Vue3创建应用对比
  • 5分钟掌握Typora插件:从文件管理小白到高效写作达人的3步法
  • ARM Cortex-R7 MPCore处理器架构与实时系统设计
  • Ascend C SetUserTag API
  • csp信奥赛C++高频考点专项训练之字符串 --【字符串排序】:宇宙总统
  • CANN ops-nn分组动态块量化算子
  • 构建 AI Agent 应用商店的构想
  • 现在不看就错过:SITS 2026唯一未公开的“AI原生”性能定义标准(IEEE P3197草案第4.2版核心条款首发解读)
  • 50 个常用 Qt 开源库 的详细解析
  • 别再默认 `all_gather` 不可导:PyTorch 2.11 把 differentiable collectives 补上之后,真正危险的是你还在按旧直觉写 loss
  • QGC界面启动避坑指南:解决QML导入路径、上下文属性注册的常见问题
  • CVE - 2024 - YIKES 安全事件:依赖项感染致恶意软件分发,加密货币蠕虫意外“救场”
  • 123项复合专利+8000+乡镇网点+8年长质保:2026空气能头部品牌实力榜单 - 匠言榜单
  • 5分钟掌握B站缓存视频转换:m4s转MP4的完整教程
  • 应对海外检测算法:英文初稿AI率飙到80%怎么救?3款工具实测攻略
  • CANN/asc-devkit Where条件选择API
  • FanControl深度解析:5步打造Windows系统完美静音散热方案
  • CherryPy与数据库集成:SQLAlchemy和ORM模式详解
  • 为什么92%的AI团队在DP集成中失败?2026奇点大会披露4个致命反模式及对应生产级修复checklist
  • League-Toolkit终极指南:英雄联盟玩家的5大高效游戏辅助神器
  • csp信奥赛C++高频考点专项训练之字符串 --【字符串排序】:字符排序
  • 【信息科学与工程学】【数据科学】第四十九篇 Apache Hive 的函数0
  • FanControl终极指南:免费开源的Windows风扇智能控制软件