SQLite WAL 模式:先把“写锁”这件事讲清楚

举报
yd_268445051 发表于 2026/10/26 13:16:56 2026/10/26
【摘要】 SQLite WAL 模式:先把“写锁”这件事讲清楚用 SQLite 做单机应用时,最常踩的坑不是 SQL 写错,而是并发一上来就报 database is locked。默认的回滚日志(rollback journal)模式下,写事务会独占整个数据库文件,读操作也得排队等。换成 WAL(Write-Ahead Logging)模式后,读和写可以并行,这个坑基本就平了。 WAL 到底改了什...

SQLite WAL 模式:先把“写锁”这件事讲清楚

用 SQLite 做单机应用时,最常踩的坑不是 SQL 写错,而是并发一上来就报 database is locked。默认的回滚日志(rollback journal)模式下,写事务会独占整个数据库文件,读操作也得排队等。换成 WAL(Write-Ahead Logging)模式后,读和写可以并行,这个坑基本就平了。

WAL 到底改了什么

开启 WAL 很简单,一条命令:

PRAGMA journal_mode=WAL;

开启后,写操作不再直接改数据库文件,而是先追加写到 -wal 文件里;读操作读的是数据库文件加 WAL 里已提交的内容。于是出现两个关键变化:第一,读不再阻塞写,写也不再阻塞读;第二,写事务之间仍然是串行的——WAL 解决的是读写冲突,不是写写冲突。

检查点(checkpoint)是 WAL 的另一个核心概念。当 WAL 文件积累到一定大小,SQLite 会把已提交的数据合并回主数据库文件,这个过程叫 checkpoint。默认是被动触发的,应用基本不用管,但要知道一件事:WAL 文件和主文件必须放在同一个目录,且 -shm 共享内存文件也要能正常创建,否则 WAL 会退化甚至报错。

三个实操要点

第一,连接要复用,不要每次操作都开关库。 频繁开关连接会让 checkpoint 和锁状态变得不可预测,长连接加连接池才是正解。Python 里可以用一个模块级连接配合线程锁,或者直接用 sqlite3 的 check_same_thread=False 加显式锁。

第二,写事务要短。 WAL 下写事务仍会互斥,一个大事务拖几秒,所有写请求都会排队。正确做法是把一次写操作拆成“准备数据”和“快速提交”两步,事务里只放真正的写语句:

import sqlite3

db = sqlite3.connect("app.db", timeout=10)
db.execute("PRAGMA journal_mode=WAL;")

def save_record(record):
    # 先在事务外算好要写的数据,事务里只做一次写入
    db.execute("BEGIN IMMEDIATE")  # 立刻拿写锁,失败会等 timeout 而不是马上报错
    try:
        db.execute("INSERT INTO records (name, value) VALUES (?, ?)", record)
        db.commit()
    except Exception:
        db.rollback()
        raise

注意 timeout=10 这个参数:它不是重试业务逻辑,而是让 SQLite 在拿不到锁时等 10 秒,短暂的锁竞争就这样被消化掉了。很多 database is locked 报错,其实把 timeout 从默认 5 秒调大、再把事务缩短就解决了。

第三,备份要按 WAL 的规矩来。 直接复制数据库文件可能丢掉 WAL 里还没 checkpoint 的数据。正确做法是用 SQLite 自带的备份 API,或者先执行 PRAGMA wal_checkpoint(TRUNCATE) 再复制文件。sqlite3 模块里有 Connection.backup(),在线备份不断服务也能用。

WAL 不是万能药

WAL 也有边界:它不适合网络文件系统(NFS 上共享内存文件不可靠),也不适合“多进程同时写、写冲突频繁”的场景——写写串行这个本质没变。如果写并发真的很高,该上 PostgreSQL 还是得上。但对绝大多数单机工具、桌面应用和嵌入式场景,WAL 模式加短事务加合理 timeout,已经足够把 SQLite 的并发表现从“勉强能用”推到“稳稳够用”。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。