暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

PostgreSQL特性矩阵解析系列20之SAVEPOINT

1118

描述

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)
    事务将插入值 13,但不会插入 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)
    事务将插入 34
    复制

    源码导读

      PostgreSQL的事物系统是一个三层系统。底层实现低级事务和子事务,在其之上是主循环的控制代码,这些代码又实现了用户可见的事务和保存点。
      同时,用户可以通过发出SQL命令BEGINCOMMITROLLBACKSAVEPOINTROLLBACK TORELEASE来改变系统的状态。

      涉及的方法主要有以下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进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

      评论