SQLite 事务(Transaction)

SQLite 中,事务(Transaction) 是确保 数据一致性原子性 的核心机制。
支持 ACID 特性:原子性、一致性、隔离性、持久性


一、事务基础语法

BEGIN [DEFERRED | IMMEDIATE | EXCLUSIVE];   -- 开始事务
-- ... SQL 语句
COMMIT;                                     -- 提交
-- 或
ROLLBACK;                                   -- 回滚
类型说明
BEGIN(默认)等同 BEGIN DEFERRED
BEGIN DEFERRED延迟锁,直到第一次写操作才锁表
BEGIN IMMEDIATE立即获取写锁,防止其他连接写入
BEGIN EXCLUSIVE独占整个数据库,读写都阻塞其他连接

二、事务类型对比

模式读操作写操作其他连接读其他连接写推荐场景
DEFERRED延迟锁可(写时冲突)读多写少
IMMEDIATE立即锁阻塞写操作需优先
EXCLUSIVE独占阻塞阻塞批量导入、重建表

三、典型使用示例

1. 转账事务(原子性)

BEGIN IMMEDIATE;

UPDATE accounts SET balance = balance - 100 WHERE id = 1;
-- 模拟错误
-- UPDATE accounts SET balance = balance + 100 WHERE id = 2;

-- 检查余额
-- SELECT RAISE(ROLLBACK, 'Insufficient funds') WHERE (SELECT balance FROM accounts WHERE id = 1) < 0;

COMMIT;

若任意一步失败,ROLLBACK 自动恢复


2. 批量插入(性能优化)

BEGIN;
INSERT INTO logs (user_id, action) VALUES (1, 'login');
INSERT INTO logs (user_id, action) VALUES (2, 'logout');
-- ... 10万条
COMMIT;

单事务比逐条提交快 10~100 倍!


3. 安全更新(IMMEDIATE)

BEGIN IMMEDIATE;
UPDATE config SET value = 'new' WHERE key = 'version';
COMMIT;

防止其他连接同时修改配置


四、自动提交模式(默认开启)

PRAGMA autocommit;  -- 返回 1(开启)
  • 每条 SQL 语句 默认是一个独立事务
  • 显式 BEGIN 后,关闭自动提交,直到 COMMIT/ROLLBACK

五、保存点(Savepoint)——局部回滚

BEGIN;

INSERT INTO users (name) VALUES ('Alice');  -- 成功

SAVEPOINT sp1;

INSERT INTO users (name) VALUES (NULL);     -- 违反 NOT NULL
-- 出错!

ROLLBACK TO sp1;  -- 只回滚到 sp1
-- Alice 保留!

INSERT INTO users (name) VALUES ('Bob');

RELEASE SAVEPOINT sp1;  -- 释放保存点
COMMIT;

类似“嵌套事务”,但 不是真嵌套


六、事务隔离级别

SQLite 只支持 SERIALIZABLE(最高隔离级别)

级别是否支持
READ UNCOMMITTED
READ COMMITTED
REPEATABLE READ
SERIALIZABLE✅(默认)

写冲突时,后写者失败,需重试


七、常见错误与解决

错误原因解决
database is locked写冲突BEGIN IMMEDIATE 或重试
cannot rollback - no transaction未开启事务BEGIN
savepoint does not exist释放顺序错按创建顺序 RELEASE

八、性能优化建议

优化点操作
批量操作包裹在 BEGIN ... COMMIT
减少锁冲突缩短事务时间
大事务分段SAVEPOINT + 定期 COMMIT
WAL 模式提高并发
PRAGMA journal_mode = WAL;  -- 推荐生产环境

九、WAL 模式下的并发

场景是否允许
多连接同时
多连接同时 ⚠️ 排队,但不阻塞读
读写并发✅ 高效

WAL = Write-Ahead Logging,比传统 ROLLBACK JOURNAL 更快


十、完整实战示例:订单系统

-- 开启 WAL
PRAGMA journal_mode = WAL;

-- 事务:创建订单 + 扣库存
BEGIN IMMEDIATE;

-- 1. 创建订单
INSERT INTO orders (user_id, total) VALUES (123, 99.99);
INSERT INTO order_items (order_id, product_id, qty, price)
VALUES (last_insert_rowid(), 5, 1, 99.99);

-- 2. 扣库存
UPDATE products SET stock = stock - 1 WHERE id = 5;

-- 3. 检查库存
-- SELECT RAISE(ROLLBACK, 'Out of stock')
-- WHERE (SELECT stock FROM products WHERE id = 5) < 0;

COMMIT;

总结:事务核心要点

项目内容
默认自动提交(每条 SQL 一个事务)
显式事务BEGIN ... COMMIT/ROLLBACK
锁策略DEFERRED(默认)、IMMEDIATEEXCLUSIVE
隔离级别SERIALIZABLE
保存点SAVEPOINT / ROLLBACK TO / RELEASE
推荐模式PRAGMA journal_mode = WAL;

快速参考卡

-- 普通事务
BEGIN; ... COMMIT;

-- 优先写锁
BEGIN IMMEDIATE; ... COMMIT;

-- 局部回滚
SAVEPOINT x; ... ROLLBACK TO x; ... RELEASE x;

-- 提高并发
PRAGMA journal_mode = WAL;

需要我帮你:

  • 分析某个操作是否需要事务
  • 优化一个慢事务
  • 写一个带重试机制的转账事务

把你的 SQL 发我!

文章已创建 2326

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

相关文章

开始在上面输入您的搜索词,然后按回车进行搜索。按ESC取消。

返回顶部