CodeGym /课程 /SQL SELF /嵌套事务:SAVEPOINT,ROLLBACK TO SAVEPOINT

嵌套事务:SAVEPOINT,ROLLBACK TO SAVEPOINT

SQL SELF
第 53 级, 课程 0
可用

在PostgreSQL里,没有真正意义上的嵌套事务。只有一个外部事务和里面的“保存点层”。

在PostgreSQL里,“嵌套事务”这个词通常指的是用保存点(savepoints),也就是用SAVEPOINT、ROLLBACK TO SAVEPOINT、RELEASE SAVEPOINT这些命令。这些不是独立的事务,而是外部事务里的特殊检查点,你可以回滚到这些点,而不用把整个事务都撤销。

生活中的例子:你在编辑器里写一大段文字,时不时按一下ctrl+s。如果你写错了,可以回到之前保存的某个版本,不会丢掉所有进度。

保存点管理的命令

为了管理嵌套事务,PostgreSQL提供了三个主要命令:

SAVEPOINT

这个命令用来创建“保存点”,你可以在需要的时候回滚到这里。保存点就像事务里的检查站。

SAVEPOINT mypoint;

ROLLBACK TO SAVEPOINT

回滚部分更改,就是回到指定保存点后,后面的更改都撤销了,但更早的更改还在同一个外部事务里保留。

ROLLBACK TO SAVEPOINT mypoint;

RELEASE SAVEPOINT

删除保存点。删了之后就不能再回滚到这个点了。

RELEASE SAVEPOINT mypoint;

例子:往多张表插数据还能回滚

假设你在做一个订单管理系统,需要同时往orders和order_items两张表插数据。如果往一张表插入出错,不应该把另一张表的数据也撤销。

BEGIN; -- 事务开始

-- 创建保存点
SAVEPOINT before_order;

-- 往orders表插入订单
INSERT INTO orders (order_id, customer_id, date)
VALUES (1, 101, CURRENT_DATE);

-- 如果这里出错 — 回滚
SAVEPOINT before_order_items;

-- 往order_items表插入商品
INSERT INTO order_items (order_id, product_id, quantity)
VALUES (1, 2001, 4);

-- 如果出问题了
-- ROLLBACK TO SAVEPOINT before_order_items;

-- 提交事务(保存更改)
COMMIT;

如果在往order_items插入数据时出错,可以回滚到before_order_items,而orders表里的更改还会保留。

实用建议和常见坑

现在你已经明白SAVEPOINT和ROLLBACK TO SAVEPOINT怎么用了,下面这些建议可以帮你少踩坑:

  1. 保存点的名字。给SAVEPOINT起个有意义又独特的名字,比如before_insert、step1啥的,这样调试的时候更容易看懂。
  2. 别忘了释放SAVEPOINT。如果你不打算再回到某个保存点了,用RELEASE SAVEPOINT把它删掉,别让事务里堆太多没用的保存点。
  3. 嵌套事务 ≠ 独立事务。记住,执行COMMIT的时候,所有保存点都会消失。外部COMMIT一旦执行,就没法再回滚了。
  4. 数据锁。即使你回滚到某个保存点,事务里加的锁还在。多用户环境下要注意这个问题。

用SAVEPOINT和ROLLBACK TO SAVEPOINT做嵌套事务,能让开发者灵活处理各种复杂情况。你可以把事务拆成多个阶段,优雅地处理错误,避免没必要的数据回滚。记住,每次看到“回滚”这个词,不一定要慌,有时候回滚才是最好的前进方式。

2
任务
SQL SELF, 第 53 级, 课程 0
已锁定
使用嵌套事务处理多步操作
使用嵌套事务处理多步操作
评论
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION