存储过程中应该尽量减少使用异常处理代码块吗?
默认情况下,任何在 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);
在上面的例子中,我们会发现,即使在数据库的运行过程中存在过多的子事务,系统的整体运行性能并不会受到多少影响。