PostgreSQL-如何从事务块外的代码运行VACUUM?

2024-04-28 10:26:29 发布

您现在位置:Python中文网/ 问答频道 /正文

我将Python与psycopg2一起使用,并尝试在插入数千行的每日操作之后运行完整的VACUUM。问题是,当我试图在代码中运行VACUUM命令时,会出现以下错误:

psycopg2.InternalError: VACUUM cannot run inside a transaction block

如何从事务块外部的代码运行此操作?

如果有区别的话,我有一个简单的DB抽象类,它的一个子集显示在下面作为上下文(不可运行,省略了异常处理和docstring,并进行了跨行调整):

class db(object):
    def __init__(dbname, host, port, user, password):
        self.conn = psycopg2.connect("dbname=%s host=%s port=%s \
                                      user=%s password=%s" \
                                      % (dbname, host, port, user, password))

        self.cursor = self.conn.cursor()

    def _doQuery(self, query):
        self.cursor.execute(query)
        self.conn.commit()

    def vacuum(self):
        query = "VACUUM FULL"
        self._doQuery(query)

Tags: 代码命令selfhostportdefpasswordconn
3条回答

经过更多的搜索,我发现了psycopg2连接对象的隔离级别属性。结果是,将其更改为0会将您移出事务块。将上述类的vacuum方法更改为以下方法可以解决此问题。注意,我还将隔离级别设置回以前的水平,以防万一(默认情况下似乎是1)。

def vacuum(self):
    old_isolation_level = self.conn.isolation_level
    self.conn.set_isolation_level(0)
    query = "VACUUM FULL"
    self._doQuery(query)
    self.conn.set_isolation_level(old_isolation_level)

This article(在该页的末尾)简要解释了此上下文中的隔离级别。

此外,您还可以通过以下方式获取真空或分析所给出的信息:

>> print conn.notices #conn is the connection object

此命令打印一个列表,其中包含诸如Vacuum之类的查询的日志消息,并分析:

INFO:  "usuario": processados 1 de 1 páginas, contendo 7 registros vigentes e 0 registros não vigentes; 7 registros amostrados, 7 registros totais estimados   
INFO:  analisando "public.usuario"

这对dba非常有用

虽然在目前的postgresql版本中,vacuum full是有问题的,但在某些大规模操作之后强制执行“vacuum analyze”或“reindex”可以提高性能,或清理磁盘使用情况。这是postgresql特有的,需要清理以对其他数据库执行正确的操作。

from django.db import connection
# Much of the proxy is not defined until this is done
force_proxy = connection.cursor()
realconn=connection.connection
old_isolation_level = realconn.isolation_level
realconn.set_isolation_level(0)
cursor = realconn.cursor()
cursor.execute('VACUUM ANALYZE')
realconn.set_isolation_level(old_isolation_level)

不幸的是,django提供的连接代理不提供设置隔离级别的访问。

相关问题 更多 >