如何回滚所有打开的PostgreSQL事务

8yoxcaq7  于 2023-01-25  发布在  PostgreSQL
关注(0)|答案(3)|浏览(146)

如何回滚特定数据库的 * 所有 * 打开的postgres事务?
我能把这两句话结合起来吗?

-- get transaction identifiers
SELECT gid FROM pg_prepared_xacts WHERE database='mydb';

-- rollback transaction by identifier
ROLLBACK PREPARED 'GID';
ttvkxqim

ttvkxqim1#

ROLLBACK PREPARED只影响准备好的两阶段提交事务,对普通事务没有影响。
如果你真的想回滚所有的 * 准备好的事务 *,那么你可以通过一个pg_prepared_xacts的循环来实现,但是,因为ROLLBACK PREPARED不能在事务中运行,你必须从一个外部客户端应用程序来实现。
我只建议在不关心数据的调试/测试系统上执行此操作。否则,请在确认单个事务不重要后手动回滚它们。2 PC通常用于数据重要的情况,并且就大多数应用而言,PREPARE TRANSACTION等同于实际的COMMIT-它们期望提交将实际到达磁盘。当然,在这种情况下,您不应该丢失准备好的事务,因为XA事务管理器(或您正在使用的任何东西)应该跟踪并恢复准备好但未提交的事务。
下面是我最近写的一个快速而肮脏的脚本,正是为了这个目的:

#!/usr/bin/env python
#
# Purges all prepared xacts from the specified database
#
# On Windows the easiest way to get psycopg2 is with ActiveState python:
#
# ActivePython (http://www.activestate.com/activepython/downloads)
# psycopg2 (http://code.activestate.com/pypm/psycopg2/)

import sys
import psycopg2
import subprocess

if len(sys.argv) != 2:
    print('Usage: cleanup_prepared_xacts.py "dbname=mydb ..."')

conn = psycopg2.connect(sys.argv[1])
conn.set_isolation_level(psycopg2.extensions.ISOLATION_LEVEL_AUTOCOMMIT)

curs = conn.cursor()
curs.execute("SELECT gid FROM pg_prepared_xacts WHERE database = current_database()")
for (gid,) in curs.fetchall():
    curs.execute("ROLLBACK PREPARED %s", (gid,))
b09cbbtk

b09cbbtk2#

我只是在这样一种情况下,我没有选择(轻松地)使用上面@克雷格Ringer的回答中的优秀Python脚本,但在我的系统上设置了Groovy-Groovy中也有同样的事情,以防它对其他人有用:

@GrabConfig(systemClassLoader=true)
@Grab(group='org.postgresql', module='postgresql', version='9.4.1212')

import groovy.sql.*

Sql.withInstance('jdbc:postgresql://pg-host-here/your-db-here', 'username', 'password', 'org.postgresql.Driver') { sql ->
  sql.eachRow('select gid from pg_prepared_xacts where database = current_database()') { row ->
    println "TX GID: ${row.gid}"
    sql.execute("rollback prepared '" + row.gid + "'")
  }
}
mzsu5hc0

mzsu5hc03#

对于准备的事务处理:

DO
$do$
DECLARE
    r RECORD;
BEGIN
    FOR r IN SELECT database, gid FROM pg_prepared_xacts
        LOOP
            PERFORM dblink_exec(format('dbname=%s', r.database), format($cmd$ROLLBACK PREPARED '%s'$cmd$, r.gid));
        END LOOP;
END;
$do$;

相关问题