首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >使用psycopg2调用postgres存储过程-事务终止无效

使用psycopg2调用postgres存储过程-事务终止无效
EN

Stack Overflow用户
提问于 2021-09-14 18:20:02
回答 2查看 310关注 0票数 0

我正在尝试使用psycopg2 (从pg_partman run_maintenance_proc())调用一个过程。

我可以从psql命令行执行一个简单的CALL partman.run_maintenance_proc();。但是当我尝试用psycopg2做同样的事情时,我遇到了这个错误:

代码语言:javascript
运行
复制
psycopg2.errors.InvalidTransactionTermination: invalid transaction termination
CONTEXT:  PL/pgSQL function partman.run_maintenance_proc(integer,boolean,boolean) line 43 at COMMIT

下面是我的代码:

代码语言:javascript
运行
复制
dbconn = psycopg2.connect(t_dsn)
cursor = dbconn.cursor()
cursor.execute('CALL partman.run_maintenance_proc()')
results = cursor.fetchone()
cursor.close()
dbconn.close()

你知道可能出了什么问题吗?

编辑:过程代码

代码语言:javascript
运行
复制
CREATE PROCEDURE @extschema@.run_maintenance_proc(p_wait int DEFAULT 0, p_analyze boolean DEFAULT NULL, p_jobmon boolean DEFAULT true)
    LANGUAGE plpgsql
    AS $$
DECLARE
 
v_adv_lock              boolean;
v_row                   record;
v_sql                   text;
v_tables_list_sql       text;
 
BEGIN
 
v_adv_lock := pg_try_advisory_lock(hashtext('pg_partman run_maintenance'));
IF v_adv_lock = false THEN
    RAISE NOTICE 'Partman maintenance already running or another session has not released its advisory lock.';
    RETURN;
END IF;
 
v_tables_list_sql := 'SELECT parent_table
            FROM @extschema@.part_config
            WHERE undo_in_progress = false
            AND automatic_maintenance = ''on''';
 
FOR v_row IN EXECUTE v_tables_list_sql
LOOP
/*
 * Run maintenance with a commit between each partition set
 * TODO - Once PG11 is more mainstream, see about more full conversion of run_maintenance function as well as turning 
 *        create_partition* functions into procedures to commit after every child table is made. May need to wait
 *        for more PROCEDURE features as well (return values, search_path, etc).
 *      - Also see about swapping names so this is the main object to call for maintenance instead of a function.
 */
    v_sql := format('SELECT %I.run_maintenance(%L, p_jobmon := %L',
        '@extschema@', v_row.parent_table, p_jobmon);
 
    IF p_analyze IS NOT NULL THEN
        v_sql := v_sql || format(', p_analyze := %L', p_analyze);
    END IF;
        
    v_sql := v_sql || ')';
 
    RAISE DEBUG 'v_sql run_maintenance_proc: %', v_sql;
 
    EXECUTE v_sql;
    COMMIT;
 
    PERFORM pg_sleep(p_wait);
 
END LOOP;
 
PERFORM pg_advisory_unlock(hashtext('pg_partman run_maintenance'));
END
$$;

注意:我注意到有一个cursor.callproc方法,但它似乎执行SELECT。如果我使用callproc会出现错误:HINT: To call a procedure, use CALL.

数据库:postgres12.5/ Psycog2版本: 2.9.1

EN

回答 2

Stack Overflow用户

发布于 2021-10-01 17:09:53

如果您使用psycopg2进行连接,则可以使用

调用

cursor.autocommit=1 cursor.execute('CALL partman.run_maintenance_proc()')

如果您是通过sqlalchemy连接的,则不能使用此选项,对于sqlalchemy:在创建引擎时将autocommit设置为True,例如)

测试导入sqlalchemy engine =sqlalchemy.create_engine(‘postgresql://

’,isolation_level="AUTOCOMMIT")

票数 1
EN

Stack Overflow用户

发布于 2021-09-15 15:07:14

啊,我想我明白问题所在了。从这里开始Transaction control

可以将连接设置为自动提交模式:这样,所有执行的命令都将立即提交,并且不可能回滚。一些命令(例如,CREATE DATABASE,VACUUM,使用事务控制…调用存储过程)要求在任何事务之外运行:为了能够从心理复制中运行这些命令,连接必须处于自动提交模式:您可以使用自动提交属性。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/69182790

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档