SQLite 中的系统事务到用户事务

发布: (2026年1月18日 GMT+8 01:09)
7 min read
原文: Dev.to

抱歉,我需要您提供要翻译的完整文本内容(除保留的 Source 链接外)。请粘贴文章的其余部分,我会按照要求将其翻译成简体中文并保留原始的格式、Markdown 语法以及代码块和 URL。

用户事务:逃离自动提交

默认情况下,SQLite 运行在 自动提交模式。每个非 SELECT 语句都会被包装在它自己的事务中:

Autocommit transaction diagram

对于 写入密集型工作负载,这种反复的设置和拆除会产生真实的开销:

  • 每条语句都会重新打开日志文件
  • 锁会反复获取和释放
  • 并发情况下争用增加

显式用户事务

为避免上述情况,应用程序可以显式定义 用户级事务

BEGIN TRANSACTION;
    INSERT INTO table1 VALUES (100);
    INSERT INTO table2 VALUES (20, 100);
    UPDATE table1 SET x = x + 1 WHERE y > 10;
    INSERT INTO table3 VALUES (1, 2, 3);
COMMIT;   -- or ROLLBACK

BEGIN 执行时,SQLite 退出自动提交模式

  • 一个 单一写事务 跨越多个语句。
  • 日志记录和锁定开销在所有写入之间摊销。

所有后续的 非 SELECT 语句 都会成为同一个用户事务的一部分。SELECT 语句仍然作为 独立的读事务 执行。

当应用程序执行:

  • COMMIT → 写事务提交。
  • ROLLBACK → 写事务中止。

之后,SQLite 会自动返回自动提交模式。

重要约束

  • SQLite 只支持 平面用户事务
  • 不允许嵌套的 BEGIN 语句。
  • 同一时间 每个数据库连接只能存在一个用户事务

此设计使 SQLite 的事务模型保持简洁且可预测。

保存点:事务内部的受控回滚

虽然 SQLite 不支持嵌套事务,但它 确实 支持 保存点,可以在事务内部提供受控的回滚机制。

保存点标记了执行过程中的一个逻辑 “良好状态”:

SAVEPOINT sp1;
-- do work
ROLLBACK TO sp1;

关键特性

  • 可以同时存在多个保存点。
  • 可以回滚到任何活动的保存点。
  • 回滚到保存点 不会 中止整个事务。

事务外的保存点

如果在用户事务 之外 创建保存点:

  1. SQLite 会隐式打开一个用户事务。
  2. 执行保存点。
  3. 当保存点被释放时自动提交。

因此,保存点在需要时充当一种 轻量级事务 抽象。

Source:

语句子事务:语句级别的原子性

即使在用户事务内部,每个非 SELECT 语句也会在其自己的子事务中运行。任意时刻只能存在一个语句子事务。SQLite 通过隐式(匿名)保存点来实现这一点。

流程如下所示:

Statement subtransaction diagram

为什么这很重要

  • 如果某个语句失败,SQLite 只会回滚该语句本身
  • 用户事务会继续执行。
  • 之前成功的语句保持不变。

除非明确指示,SQLite 不会因为单个语句的失败而中止整个事务。

示例:语句子事务的实际运作

BEGIN TRANSACTION;

INSERT INTO table1 VALUES (100);
INSERT INTO table2 VALUES (20, 100);
UPDATE table1 SET x = x + 1 WHERE y > 10;
INSERT INTO table3 VALUES (1, 2, 3);

COMMIT;

执行模型

  • 每条语句在它自己的子事务中运行。
  • 如果 UPDATE 触发约束冲突:
    • UPDATE 所做的所有更改都会回滚。
    • 周围的 INSERT 仍然保持有效。
    • 最后的 COMMIT 会持久化所有成功的操作。

这就是 SQLite 能够在部分失败后干净恢复,而无需强制应用程序重新启动事务的原因。

冲突解决:约束违规时会发生什么

当在 INSERTUPDATE 期间发生约束违规时,SQLite 会应用 冲突解决算法。每种策略定义回滚传播的范围。

Conflict resolution diagram

这些模式决定失败是仅局限于语句子事务本地,还是上升到外部用户事务。

综合全部

SQLite 的事务模型分层:

  • 系统事务 – 保证单个语句的原子执行。
  • 用户事务 – 将日志记录和锁定成本在多次写入之间摊销。
  • 保存点 – 允许在不终止整个事务的情况下进行受控回滚。
  • 语句子事务 – 即使在长事务内部,也确保每条语句的原子性。

尽管仅支持 平面事务,SQLite 通过保存点和子事务实现了细粒度的正确性,而不会向应用程序暴露不必要的复杂性。

我关于 SQLite 的实验和实操代码放在这里:
lovestaco/sqlite

参考文献

  1. SQLite Database System: Design and Implementation – Sibsankar Haldar。

  2. FreeDevTools
    👉 查看:FreeDevTools

欢迎任何反馈或贡献!

它是在线的、开源的,随时可供任何人使用。

在 GitHub 上点星: HexmosTech/FreeDevTools

Back to Blog

相关文章

阅读更多 »

数据库事务

事务是 SQL 数据库工作方式的基础。每天都有数万亿次事务执行,遍布依赖 SQL 的数千个应用程序。