Redrock Postgres 文档
主页 切换暗/亮/自动模式 切换暗/亮/自动模式 切换暗/亮/自动模式 返回首页
编辑页面

存储过程中应该尽量减少使用异常处理代码块吗?

问题描述

默认情况下,任何在 PL/pgSQL 函数中发生的错误会中止该函数的执行,而且实际上会中止其周围的事务。你可以使用一个带有EXCEPTION子句的BEGIN块俘获错误并且从中恢复。

Redrock Postgres 会使用子事务来实现存储过程的异常处理代码块。那么,我们是否需要在使用LOOP块的循环处理过程中,避免使用异常处理代码块,或者避免调用包含异常处理代码块的其他存储过程,以防止产生过多的子事务呢?过多的子事务是否会引起系统性能的下降呢?

问题解答

Redrock Postgres 是基于撤消日志记录位置实现的子事务,这些子事务不过是事务执行过程中的一个临时标记,它们并不需要分配独立的事务 ID,不会对系统的性能产生多少影响,您可以放心地使用存储过程异常处理代码块这些基础特性。

问题验证

在下面的例子中,我们创建了一个存储过程,在存储过程中,循环更新表t_table中的多条记录,在执行这个存储过程的同时,我们可以使用 pgbench 在数据库上运行基准测试。

CREATE TABLE t_table (id integer, name text);

INSERT INTO t_table (id, name)
  SELECT i, 'dummy' FROM generate_series(1, 1000) AS s(i);

CREATE OR REPLACE FUNCTION func_exception_in_loop(num integer)
  RETURNS void AS $$
DECLARE
  i integer;
  t text;
BEGIN
  FOR i IN 1..num LOOP
    BEGIN
      UPDATE t_table SET name = 'test' WHERE id = i;
      SELECT pg_sleep(0.1) into t;
    EXCEPTION WHEN OTHERS THEN
      RAISE WARNING 'update row error';
    END;
  END LOOP;
END $$ LANGUAGE plpgsql;

SELECT func_exception_in_loop(1000);

在上面的例子中,我们会发现,即使在数据库的运行过程中存在过多的子事务,系统的整体运行性能并不会受到多少影响。