SQLite Tcl接口:内层事务提交外层回滚可行吗?如何预存内存库状态?
问题与解决方案
核心疑问
在同时操作磁盘数据库与内存数据库的事务流程中,若触发异常,我希望先将内存数据库的当前状态写入磁盘,再回滚整个事务。想明确:通过Savepoint创建的内层事务,能否在外层事务执行回滚时保持提交状态?
我查阅了SQLite官方文档,文档仅提及支持回滚到Savepoint后提交事务剩余部分,未涉及这种反向场景,因此仍有疑惑。
已尝试的无效方案
- 内置备份方法与
VACUUM INTO:因写事务锁定了内存数据库,无法生效。 - 调整代码逻辑:先完成验证再写入磁盘数据库,以便先提交内存库写入再退出,但这种逻辑并非总能适配业务场景。
可行的状态捕获方案(非事务嵌套方案)
目前尚未找到通过嵌套事务实现需求的方法,但可以通过SQLite Tcl接口的序列化功能,在回滚前捕获内存数据库状态并写入磁盘,用于问题排查。该方案序列化整个数据库,暂无法实现仅写入特定表且不被回滚的操作,示例代码如下:
package require sqlite3 sqlite3 mem ":memory:"; mem eval { create table docs (id integer); insert into docs values (1),(2),(3); begin immediate; update docs set id=4 where id=2; } if {1} { set fp [open memtest.db wb] set s [mem serialize main] chan puts $fp $s close $fp mem eval {rollback;} } else { mem eval {commit;} } # 输出原内存库回滚后的数据:1 2 3 chan puts stdout [mem eval {select * from docs;}] # 从磁盘读取序列化后的数据库验证 sqlite3 dbusr memtest.db -create false -readonly false # 输出磁盘库中保存的回滚前状态:1 4 3 chan puts stdout [dbusr eval {select * from docs;}] # 创建新内存库并反序列化捕获的状态 sqlite3 mem_ds ":memory:"; mem_ds deserialize main $s # 再次输出原内存库数据:1 2 3 chan puts stdout [mem eval {select * from docs;}] # 输出反序列化后的新内存库数据:1 4 3 chan puts stdout [mem_ds eval {select * from docs;}]
内容的提问来源于stack exchange,提问作者Gary
相关产品推荐
相关产品推荐

