SQLite 事务入门:用一次模拟转账理解提交和回滚
假设一个账户要向另一个账户转出 20 个单位:先扣减余额,再增加余额。如果只完成第一步,记录就不一致了。数据库事务可以把相关操作组织在一起,让应用在确认全部步骤成功后提交,遇到问题时回滚。
一、准备独立的练习库
下面使用 SQLite 命令行工具。请在新建的空练习目录中运行,确保不会操作真实数据:
sqlite3 transaction-demo.db
进入提示符后,依次执行以下 SQL。余额以整数表示,便于观察:
CREATE TABLE accounts (name TEXT PRIMARY KEY, balance INTEGER NOT NULL);
INSERT INTO accounts VALUES ('A', 100), ('B', 50);
SELECT * FROM accounts ORDER BY name;
初始结果应为 A 的余额 100、B 的余额 50。SQL 语句末尾的分号表示一条语句结束,命令行工具据此执行输入。
二、尝试回滚
先开启事务,模拟从 A 扣除 20,但随后决定取消:
BEGIN;
UPDATE accounts SET balance = balance - 20 WHERE name = 'A';
SELECT * FROM accounts ORDER BY name;
ROLLBACK;
SELECT * FROM accounts ORDER BY name;
第一次查询发生在事务内,当前连接能看到 A 的余额变为 80;回滚后的查询应恢复为 100 和 50。ROLLBACK 撤销的是当前事务中尚未提交的修改,不会撤销事务开始前已经提交的建表和初始数据。
三、完成一次提交
接下来同时更新两个账户,然后提交:
BEGIN;
UPDATE accounts SET balance = balance - 20 WHERE name = 'A';
UPDATE accounts SET balance = balance + 20 WHERE name = 'B';
COMMIT;
SELECT * FROM accounts ORDER BY name;
预期结果为 A:80、B:70,总额仍为 150。退出命令行工具可输入 .quit;重新打开同一个数据库文件并查询,可以检查已提交的结果。
四、事务不能代替业务检查
上面的语句假定两个账户都存在且余额足够,只用于演示。真实应用需要验证账户、金额和余额,并确认每一步影响了预期的记录数:例如 UPDATE 找不到账户时可能只是影响零行,并不一定自动报错。应用应在检查失败时明确执行回滚,不能继续提交另一半操作。
也不要假设任何 SQL 错误都会自动回滚整个事务。遇到错误后,应用需要按具体错误和事务状态处理,适时回滚;提交本身也可能失败,必须检查结果。生产环境还要考虑并发访问、权限和审计。
五、先观察再迁移到项目
练习时可以先只运行到第一条 UPDATE,用 SELECT 观察当前连接看到的状态,再分别尝试 ROLLBACK 和 COMMIT。一次只改变一个条件,并记录前后的余额,有助于分清“暂时修改”和“已提交”。在真实项目中,应使用应用框架提供的事务和异常处理机制,并为失败路径编写验证。
- 点赞
- 收藏
- 关注作者
评论(0)