DBMS_TRANSACTION
是一个兼容Oracle语法的内置包,用于在PL/SQL程序块(如存储过程、函数)中实现对事务的精细化控制。当您需要在一段复杂的业务逻辑中撤销部分操作而非回滚整个事务时,可以使用该包提供的保存点(Savepoint)功能,实现更灵活的事务管理。
功能简介
PolarDB PostgreSQL版(兼容Oracle)支持以下四个函数:
SAVEPOINT
:标记事务中的保存点,用于回滚到指定保存点。ROLLBACK_SAVEPOINT
:回滚到指定保存点,用于撤销保存点后的操作。COMMIT
:提交当前事务,用于永久化更改数据。ROLLBACK
:回滚整个事务,用于撤销所有未提交的操作。
前提条件
仅支持Oracle语法兼容 2.0,且内核小版本需为2.0.14.17.34.0及以上版本。
注意事项
使用
SAVEPOINT
和ROLLBACK_SAVEPOINT
前,请先开启polar_default_pl_stmt_transaction_rollback
参数。COMMIT
或ROLLBACK
会结束当前事务,如需继续使用,需重新开始新事务。频繁使用
SAVEPOINT
可能会增加事务开销,建议合理规划事务的粒度。不支持
BEGIN_WORK
及SET_TRANSACTION
等高级功能。EXECUTE IMMEDIATE
场景中,若需使用COMMIT
/ROLLBACK
,请先开启polar_enable_commit_in_execute_immediate
参数。
SAVEPOINT
在事务中设置保存点(Savepoint),用于后续回滚到该点。
语法
DBMS_TRANSACTION.SAVEPOINT(savepoint_name VARCHAR2);
参数说明
参数 | 描述 |
| 保存点的名称。 |
示例
DECLARE
BEGIN
-- 插入测试数据
INSERT INTO test_table (id, name) VALUES (1, 'Alice');
-- 设置保存点
DBMS_TRANSACTION.SAVEPOINT('sp1');
-- 执行可能失败的操作
INSERT INTO test_table (id, name) VALUES (2, 'Bob');
-- 提交事务
COMMIT;
END;
事务开始后,插入一条数据,并记录保存点sp1。
若后续操作失败,可通过
ROLLBACK_SAVEPOINT
回滚到sp1。最后
COMMIT
提交事务,所有更改生效。
ROLLBACK_SAVEPOINT
回滚事务到指定保存点(Savepoint),撤销保存点之后的操作。
语法
DBMS_TRANSACTION.ROLLBACK_SAVEPOINT(savepoint_name VARCHAR2);
参数说明
参数 | 描述 |
savepoint_name | 保存点的名称。 |
示例
DECLARE
BEGIN
-- 插入第一条记录
INSERT INTO test_table (id, name) VALUES (1, 'Alice');
-- 设置保存点
DBMS_TRANSACTION.SAVEPOINT('sp1');
-- 插入第二条记录(可能失败)
INSERT INTO test_table (id, name) VALUES (2, 'Bob');
-- 回滚到保存点 sp1
DBMS_TRANSACTION.ROLLBACK_SAVEPOINT('sp1');
-- 提交事务
COMMIT;
END;
事务开始后,插入一条数据Alice,并记录保存点sp1。
插入第二条数据,并通过
ROLLBACK_SAVEPOINT('sp1')
回滚,Bob的记录不会被保留。最后
COMMIT
提交事务,仅保留了Alice的插入数据。
COMMIT
提交当前事务,使所有更改永久生效。
语法
DBMS_TRANSACTION.COMMIT();
示例
DECLARE
BEGIN
-- 插入两条记录
INSERT INTO test_table (id, name) VALUES (1, 'Alice');
INSERT INTO test_table (id, name) VALUES (2, 'Bob');
-- 提交事务
DBMS_TRANSACTION.COMMIT();
END;
事务开始后,插入两条数据。
调用COMMIT提交事务。所有更改将被永久写入数据库。
若未显式提交,事务在程序块结束时自动提交(取决于数据库配置)。
ROLLBACK
回滚整个事务,撤销所有未提交的更改。
语法
DBMS_TRANSACTION.ROLLBACK();
示例
DECLARE
BEGIN
-- 插入第一条记录
INSERT INTO test_table (id, name) VALUES (1, 'Alice');
-- 模拟错误
IF 1 = 1 THEN
RAISE_APPLICATION_ERROR(-20001, '人为触发错误');
END IF;
-- 提交事务(不会执行)
DBMS_TRANSACTION.COMMIT();
EXCEPTION
WHEN OTHERS THEN
-- 回滚整个事务
DBMS_TRANSACTION.ROLLBACK();
DBMS_OUTPUT.PUT_LINE('事务已回滚');
END;
事务开始后,插入一条数据Alice后,触发人为错误。
在异常处理
EXCEPTION
中调用ROLLBACK()
,撤销所有未提交的更改。最后事务被回滚,test_table中无新增记录。