为什么通过Lua脚本访问SQLite会删除WAL模式下的-wal文件?
核心原因
WAL文件被删除的根本原因是Lua脚本中打开的数据库连接未启用WAL模式:SQLite的journal_mode是连接级配置,仅在C侧的连接上设置WAL模式不生效,Lua脚本调用lsqlite3.open()打开的是独立新连接,默认使用DELETE日志模式,该连接访问数据库时会自动将日志模式切回DELETE,直接删除现有-wal文件,之前在C侧设置的SQLITE_FCNTL_PERSIST_WAL对Lua侧的独立连接完全无效。
修复方案
- Lua侧打开数据库后第一时间设置与C++侧对齐的WAL相关参数,修改后的Lua脚本如下:
function prequire(name) local status, lib = pcall(require, name) if(status) then return lib end -- 加载库失败直接返回空 return nil end print("start lua") local sqlite3 = prequire("lsqlite3complete") if sqlite3 == nil then print('No lsqlite3') return end local db = sqlite3.open('/data/data/ru.chromesearcher.sqlitewal/files/database.sqlite3') if db == nil then print("db open failed") return end -- 新增WAL模式配置,和C++侧配置保持一致 db:exec([[ PRAGMA journal_mode=WAL; PRAGMA synchronous=FULL; ]]) print("query start") local stmt = db:prepare('SELECT * FROM paymentevents where pe_amount=?') local amount = 3000 stmt:bind_values(amount) stmt:finalize() db:close()
- 如需全局启用WAL持久化,需在所有数据库连接(包括C++、Lua侧的所有连接)上都设置
SQLITE_FCNTL_PERSIST_WAL参数,避免单个连接未配置导致规则失效。 - 配置后可执行
PRAGMA journal_mode;查询返回值,确认返回结果为wal即可确认配置生效。
之前尝试无效的原因
PRAGMA locking_mode=EXCLUSIVE、synchronous=EXTRA均不影响日志模式的连接级特性,只要存在任意一个使用DELETE模式的连接访问数据库,就会触发WAL文件删除- 仅在C侧设置
SQLITE_FCNTL_PERSIST_WAL仅作用于当前C连接,对Lua侧新建的独立连接不生效
内容的提问来源于stack exchange,提问作者chromesearcher
相关产品推荐
相关产品推荐

