SQLite C接口:如果事务回滚失败,会发生什么?

时间:2019-12-19 13:11:37

标签: sql database sqlite transactions rollback

我为使用以下方法利用SQLite的项目编写了许多API:

sqlite3_exec(mydatabase, "BEGIN;", nullptr, nullptr, nullptr);
/* perform several INSERT, SELECT, UPDATE, DELETE queries on the database */
if(/* problem detected */){
    sqlite3_exec(mydatabase, "ROLLBACK;", nullptr, nullptr, nullptr);
} else {
    sqlite3_exec(mydatabase, "COMMIT;", nullptr, nullptr, nullptr);
}

我的问题是:如果回滚语句失败,会发生什么?我想我可以检查commit语句和回滚的返回值以防出现错误,但是我不知道如果回滚失败该怎么办。

此外,我已经编写了代码,假设我可以做这样的事情:

sqlite3_exec(mydatabase, "BEGIN;", nullptr, nullptr, nullptr);
/* INSERT data in the database */
/* UPDATE or SELECT records in the database where the record could be a record already stored in the db
or a record inserted with the INSERT statement above */
if(/* problem detected */){
    sqlite3_exec(mydatabase, "ROLLBACK;", nullptr, nullptr, nullptr);
} else {
    sqlite3_exec(mydatabase, "COMMIT;", nullptr, nullptr, nullptr);
}

因此,基本上我假设如果我启动一个事务,更改数据库中的某些内容并在数据库中搜索修改后的行,则即使事务仍在运行并且尚未发出提交,该更改也将立即可见。这是正确的吗?

谢谢

1 个答案:

答案 0 :(得分:1)

在相同连接(即相同进程和相同连接对象)的上下文中,在事务内部进行的对数据库的所有更改对于同一事务中的后续语句都是可见的。交易的整个目的是累积相关的更改,然后一次提交所有更改,或者一起拒绝(即回滚)所有更改。如果不是这种情况,则交易的整个目的将被取消。


如果回滚失败,则应检查result/error codes并进行相应处理。并非所有故障都表明数据库存在严重问题。

先前提交和/或回滚的事务无法再次回滚,因此会导致错误。这将指示某种类型的逻辑/流错误,但不一定表示数据库完整性有问题。但是,如果代码的一部分尝试回滚但事务已经提交,则根据您的特定要求和业务逻辑,数据可能不会处于有效状态。只有您可以决定如何处理此类错误。修正错误?忽略错误?

错误代码SQLITE_BUSY意味着另一个连接已临时锁定了数据库,因此它也可能防止回滚(不确定此操作)。简单的延迟和重试就足以解决此问题。

其他错误可能表示更严重的情况,例如数据库连接丢失或日志文件损坏等。您如何处理此问题完全取决于您的应用程序以及数据库对应用程序的重要性。错误是否应该升级并终止整个程序?简单登录并忽略?也许您的代码可以进一步分析连接和/或数据库文件并尝试恢复?

相关问题