描述
SAVEPOINT
在当前事务中建立一个新保存点。保存点是事务内的一种特殊标记,它允许所有在它被建立之后执行的命令被 回滚,把该事务的状态恢复到它处于保存点时的样子。
在比较大的事务中,可以把执行过程分为几个步骤,每个步骤执行完成后创建一个保存点,后续步骤执行失败时,可回滚到之前的保存点,而不必回滚整个事务。
实验
ROLLBACK TO SAVEPOINT — 回滚到一个保存点
RELEASE SAVEPOINT — 销毁一个之前定义的保存点
postgres=# create table test(id int);
CREATE TABLE
postgres=# BEGIN;
BEGIN
postgres=# INSERT INTO test VALUES (1);
INSERT 0 1
postgres=# SAVEPOINT my_savepoint;
SAVEPOINT
postgres=# INSERT INTO test VALUES (2);
INSERT 0 1
postgres=# ROLLBACK TO SAVEPOINT my_savepoint;
ROLLBACK
postgres=# INSERT INTO test VALUES (3);
INSERT 0 1
postgres=# COMMIT;
COMMIT
postgres=# select * from test;
id
----
1
3
(2 rows)
事务将插入值 1 和 3,但不会插入 2。
建立并且稍后销毁一个保存点:
postgres=# BEGIN;
BEGIN
postgres=# INSERT INTO test VALUES (3);
INSERT 0 1
postgres=# SAVEPOINT my_savepoint;
SAVEPOINT
postgres=# INSERT INTO test VALUES (4);
INSERT 0 1
postgres=# RELEASE SAVEPOINT my_savepoint;
RELEASE
postgres=# COMMIT;
COMMIT
postgres=# select * from test;
id
----
3
4
(2 rows)
事务将插入 3 和 4。
复制
源码导读
PostgreSQL的事物系统是一个三层系统。底层实现低级事务和子事务,在其之上是主循环的控制代码,这些代码又实现了用户可见的事务和保存点。
同时,用户可以通过发出SQL命令BEGIN、COMMIT、ROLLBACK、SAVEPOINT、ROLLBACK TO或RELEASE来改变系统的状态。
涉及的方法主要有以下6个
1.BeginTransactionBlock
2.EndTransactionBlock
3.UserAbortTransactionBlock
4.DefineSavepoint
5.RollbackToSavepoint
6.ReleaseSavepoint
源码路径
src/backend/access/transam/xact.c
/*
* DefineSavepoint
* This executes a SAVEPOINT command.
*/
void
DefineSavepoint(const char *name)
{
TransactionState s = CurrentTransactionState;
/*
* Workers synchronize transaction state at the beginning of each parallel
* operation, so we can't account for new subtransactions after that
* point. (Note that this check will certainly error out if s->blockState
* is TBLOCK_PARALLEL_INPROGRESS, so we can treat that as an invalid case
* below.)
*/
... ...
}
/*
* ReleaseSavepoint
* This executes a RELEASE command.
*
* As above, we don't actually do anything here except change blockState.
*/
void
ReleaseSavepoint(const char *name)
{
TransactionState s = CurrentTransactionState;
TransactionState target,
xact;
/*
* Workers synchronize transaction state at the beginning of each parallel
* operation, so we can't account for transaction state change after that
* point. (Note that this check will certainly error out if s->blockState
* is TBLOCK_PARALLEL_INPROGRESS, so we can treat that as an invalid case
* below.)
*/
... ...
}
/*
* RollbackToSavepoint
* This executes a ROLLBACK TO <savepoint> command.
*
* As above, we don't actually do anything here except change blockState.
*/
void
RollbackToSavepoint(const char *name)
{
TransactionState s = CurrentTransactionState;
TransactionState target,
xact;
/*
* Workers synchronize transaction state at the beginning of each parallel
* operation, so we can't account for transaction state change after that
* point. (Note that this check will certainly error out if s->blockState
* is TBLOCK_PARALLEL_INPROGRESS, so we can treat that as an invalid case
* below.)
*/
... ...
}
复制
参考
http://postgres.cn/docs/12/sql-savepoint.html
src/backend/access/transam/README
文章转载自CP的PostgreSQL厨房,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。