在表中写入异常消息

时间:2019-06-18 09:20:09

标签: postgresql exception transactions

我具有以下功能,该功能由Web API调用以导入一些上传的数据。还有一个upload_log表,该表保存上传状态,并且可以通过API进行轮询。

我的问题特定于Postgresql事务管理:我知道BEGIN...END块之间的所有事务都是PG中的事务,并且一旦一个语句失败,它将自动回滚。

因此,永远不要将异常写入到upload_log表中?

尽管如此,我在我的upload_log中收到错误消息,但我问自己为什么会这样。

  • 是因为嵌套的函数调用PERFORM...吗?
  • 是因为EXCEPTION WHEN OTHERS...之后可以在表中写入内容吗?
  • 我是否必须在EXCEPTION块中显式调用ROLLBACK
  • 我是否必须将DBLink写为“自主事务”?

    CREATE OR REPLACE FUNCTION finalize_upload(sync_id in varchar)
    RETURNS void AS $$
    DECLARE
       vCount numeric;
       err1 text;
       err2 text;
       err3 text;
    BEGIN
       -- Mark as Upload in Progress
       update upload_log
       set
          sync_status='1'
       where
          upload_log.gto_sync_id=finalize_upload.sync_id;

       begin
          vCount := 1;

          -- do some heavy stuff
          -- move data from import tables into production
          perform finalize_upload_specific(finalize_upload.sync_id);

       exception when others then
          GET STACKED DIAGNOSTICS err1 = MESSAGE_TEXT,
                            err2 = PG_EXCEPTION_DETAIL,
                            err3 = PG_EXCEPTION_HINT;

          -- Mark Upload as failed
          update upload_log
          set
             END_DATE=current_timestamp,
             sync_status='-1',
             err_hint=err1||' '||err2||' '||err3
          where
             upload_log.sync_id=finalize_upload.sync_id;
       end
       ;
    END
    $$ LANGUAGE plpgsql;

1 个答案:

答案 0 :(得分:1)

PL / pgSQL块中BEGIN和关联的EXCEPTION之间的所有操作都将在子事务中执行。

如果抛出任何已处理的异常,则子事务将回滚,但封闭的事务将继续。异常处理程序中的UPDATE将被提交,因为它已经在要回滚的子事务之外。

使用伪代码和SQL保存点进行说明:

START TRANSACTION;
UPDATE upload_log SET sync_status='1' ...;
SAVEPOINT a;
SELECT finalize_upload_specific($1);
-- if an exception was thrown:
ROLLBACK TO SAVEPOINT a;
RELEASE SAVEPOINT a;
UPDATE upload_log SET sync_status='-1' ...;
COMMIT;
-- else
ROLLBACK;