作者:烟熏装-_265 | 来源:互联网 | 2023-10-12 03:04
我正在一个涉及SQLite的项目中,我只有一个数据库文件,现在我正在测试我的应用程序在断电或应用程序崩溃的情况下的行为。
我已成功测试了电源中断情况下日志文件的回滚,但是我正在为应用程序崩溃(例如由于未捕获的异常)而导致的SQLite行为苦苦挣扎。
让我们假设这种情况(真实数据库上的操作比单个插入要复杂得多,这就是为什么我要显式使用事务的原因):
sqlite3_exec(db,"BEGIN;",nullptr,nullptr);
/* other code (may be select,delete,update on the db or something not related to the db) */
sqlite3_exec(db,"INSERT INTO mytable(myvalue) VALUES(10);",nullptr);
throw "exception"; /* something throws an exception here */
sqlite3_exec(db,"COMMIT;",nullptr);
上面的代码结果是我在磁盘上还有一个日记文件。我的期望是,崩溃后我一开始与数据库建立连接,就会自动读取日志文件并执行回滚。
我实际上注意到的是,直到我开始另一笔交易之前,日志文件才被触摸,然后独立于此新交易(提交或回滚)的结果,我在上述代码中抛出之前所做的更改将自动回滚。这是预期的行为吗?也许是因为日志文件不是热门新闻文件,因为在回滚或提交期间没有发生崩溃?
编辑:可能我找到了这种现象的原因。默认情况下,SQLite中的自动提交模式是启用的,并且仅在手动启动事务时才禁用,然后在手动事务完成(提交或回滚)后再次启用。如果在事务开始之后但事务结束之前发生崩溃或断电,则将禁用自动提交,并且当再次打开数据库时,自动提交仍将被禁用,因此除非处理了日志,否则将不会处理日志文件新事务已启动和完成(通过回滚或提交)。如果在执行提交或回滚时发生崩溃或断电,则不会发生这种情况,因为在那一刻,再次启用了自动提交功能,因此新的时间SQLite将自动进行回滚。