我使用Python psycopg2我要运行完整的 VACUUM 之后的每日操作,这将插入几千行。问题是,当我试运行 VACUUM 命令在我的代码,我得到的以下错误:

psycopg2.InternalError: VACUUM cannot run inside a transaction block

我怎么跑这种代码之外的交易块?

如果它使一个差的,我有一个简单的DB类抽象的一个子集显示以下方面(不是可运行的,除非处理和文档字符串略和行跨越所做的调整):

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)
有帮助吗?

解决方案

经过更多搜索后,我发现了psycopg2连接对象的isolation_level属性。事实证明,将此更改为 0 会使您退出事务块。将上述类的真空方法改为以下解决方案。请注意,我还将隔离级别设置回以前的情况(默认情况下似乎是 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)

本文(靠近该页末尾)提供隔离的简要说明在这种情况下的水平。

其他提示

此外,您还可以使用以下方法获取Vacuum或Analyze提供的消息:

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

此命令打印一个列表,其中包含查询的日志消息,如Vacuum和Analyze:

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中真空充满是有问题的,但在某些大规模操作之后强制进行“真空分析”或“重新索引”可以提高性能或清理磁盘使用情况。这是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提供的连接代理不提供对set_isolation_level的访问。

请注意,如果您使用Django with South执行迁移,则可以使用以下代码执行 VACUUM ANALYZE

def forwards(self, orm):

    db.commit_transaction()
    db.execute("VACUUM ANALYZE <table>")

    #Optionally start another transaction to do some more work...
    db.start_transaction()

我不知道psycopg2和PostgreSQL,但只有apsw和源码的,所以我想我可以不给"psycopg2"的帮助。

但它缝我,PostgreSQL可能的工作相似源码,它具有两种模式运作:

  • 外交事务模块:这是语义上等同于有一个事务的框周围每一个SQL操作
  • 内部事务框,标志是"开始交易"结束通过"交易"

在这种情况下,问题可能是内部的访问层psycopg2.当它通常的方式运作,交易implicitely插入,直至提交,就不可能"标准的方式"来做一个真空。

当然它可能是可能的,即"psycopg2"具有其特殊的"真空"的方法,或一个特殊的操作模式,在没有隐含的交易是开始。

在没有这种可能性存在,没有保持一个单一选项(没有改变访问层;-)):

大多数数据库有一个壳程序访问该数据库。该程序可能会运行这个壳程序与管(进入该真空的命令成壳),因此使用命令行程序来使这一真空。由于真空是一个缓慢的操作这样的,开始一个外部程序将neglectible.当然,实际程序应当提交所有uncommited工作之前,他有可能是一个死锁状况-真空必须等待,直到结束你的最后一次交易。

不要这样做 - 你不需要VACUUM FULL。实际上如果你运行稍微版本的Postgres(比如说> 8.1),你甚至不需要手动运行普通的VACUUM。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top