如何在PostgreSQL中实现审计表插入后并行调用两个procedure
PostgreSQL 审计表插入时并行执行两个无依赖存储过程的可行方案
方案1:使用pg_background扩展实现异步并行
pg_background是PostgreSQL官方生态的第三方扩展,支持提交后台异步任务,不需要当前会话等待任务执行完成,多个提交的任务会自动并行运行。
操作步骤:
- 安装扩展(需要超级用户权限):
CREATE EXTENSION pg_background;
- 修改审计表的触发器函数,替换原有顺序调用存储过程的逻辑:
CREATE OR REPLACE FUNCTION audit_insert_trigger_func() RETURNS TRIGGER AS $$ BEGIN -- 分别提交两个存储过程到后台执行,可传入新插入审计条目的ID等必要参数 PERFORM pg_background_submit(format('CALL procedure1(%L)', NEW.id)); PERFORM pg_background_submit(format('CALL procedure2(%L)', NEW.id)); RETURN NEW; END; $$ LANGUAGE plpgsql VOLATILE;
- 绑定触发器到审计表A(如果原有触发器已存在,只需要更新触发器函数即可):
CREATE TRIGGER trg_audit_after_insert AFTER INSERT ON audit_a FOR EACH ROW EXECUTE FUNCTION audit_insert_trigger_func();
优势:配置简单,代码侵入性极低,不需要额外运维组件
方案2:使用内置dblink扩展实现异步调用
dblink是PostgreSQL内置的扩展,不需要额外安装第三方组件,支持通过异步数据库会话执行任务,不同会话的任务天然并行运行。
操作步骤:
- 开启内置扩展:
CREATE EXTENSION IF NOT EXISTS dblink;
- 修改触发器函数:
CREATE OR REPLACE FUNCTION audit_insert_trigger_func() RETURNS TRIGGER AS $$ BEGIN -- 建立独立异步会话执行procedure1 PERFORM dblink_connect('proc1_conn', 'dbname=' || current_database()); PERFORM dblink_send_query('proc1_conn', format('CALL procedure1(%L)', NEW.id)); -- 建立另一个独立异步会话执行procedure2 PERFORM dblink_connect('proc2_conn', 'dbname=' || current_database()); PERFORM dblink_send_query('proc2_conn', format('CALL procedure2(%L)', NEW.id)); RETURN NEW; END; $$ LANGUAGE plpgsql VOLATILE;
优势:完全使用内置能力,不需要引入第三方依赖,生产环境兼容性高
方案3:任务队列表 + 外部Worker实现
该方案将存储过程执行任务解耦到数据库外部,适合对可靠性要求高、需要任务重试、执行日志可追溯的生产场景。
操作步骤:
- 新建任务队列表存储待执行的存储过程任务:
CREATE TABLE audit_proc_task ( id SERIAL PRIMARY KEY, audit_record_id INT NOT NULL, proc_name VARCHAR(128) NOT NULL, task_status VARCHAR(32) DEFAULT 'PENDING', create_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, finish_at TIMESTAMP, error_msg TEXT );
- 修改触发器函数,插入任务记录即可,不需要直接调用存储过程:
CREATE OR REPLACE FUNCTION audit_insert_trigger_func() RETURNS TRIGGER AS $$ BEGIN INSERT INTO audit_proc_task (audit_record_id, proc_name) VALUES (NEW.id, 'procedure1'), (NEW.id, 'procedure2'); RETURN NEW; END; $$ LANGUAGE plpgsql VOLATILE;
- 开发独立的外部Worker程序(可使用Python/Go/Java等任意语言),多线程并行拉取
PENDING状态的任务,调用对应存储过程,执行完成后更新任务状态,如果执行失败可记录错误信息并重试。
优势:完全不占用触发器执行时间,任务可控性高,支持失败重试、监控告警等扩展能力,适合高并发生产环境
选型建议
- 测试环境/小流量场景:优先选pg_background方案,配置成本最低
- 生产环境不允许安装第三方扩展:选dblink方案,使用内置能力即可实现
- 高并发、高可靠要求的生产场景:选任务队列+外部Worker方案,稳定性和可扩展性最好
内容的提问来源于stack exchange,提问作者Santhosh reddy
相关产品推荐
相关产品推荐

