PostgreSQL的 - 如何运行代码外部事务块真空?(PostgreSQL - how to r

2019-06-23 16:04发布

我使用Python和psycopg2和我试图运行一个完整的VACUUM日常操作其插入几千行之后。 问题是,当我尝试运行VACUUM我的代码中的命令,我得到以下错误:

psycopg2.InternalError: VACUUM cannot run inside a transaction block

如何从一个事务块外面的代码运行吗?

如果它的确与众不同,我有一个简单的数据库抽象类,它的一个子集,显示下面的上下文(不可运行,异常处理和省略文档字符串并提出跨线调整):

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)

Answer 1:

更多的搜索后,我发现了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)

这篇文章 (近页面上的一端)提供隔离级别在这方面的简要说明。



Answer 2:

此外,您还可以得到由真空给出的消息或使用分析:

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

此命令打印与像真空和分析查询的日志信息的列表:

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"

这可以是数据库管理员有用的^^



Answer 3:

虽然真空完全是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。



Answer 4:

注意:如果你使用Django与韩国进行迁移,你可以使用下面的代码执行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()


Answer 5:

我不知道psycopg2和PostgreSQL,但只有APSW和SQLite,所以我觉得我不能给出一个“psycopg2”的帮助。

但它接缝对我来说,PostgreSQL的可能工作为SQLite的不相似,它有两种操作模式:

  • 外一个事务块:这是语义上等价于有大约每一个SQL操作的事务块
  • 在一个事务块,由“BEGIN TRANSACTION”标记和“END TRANSACTION”结束

如果是这样的话,问题可能是接入层psycopg2内。 当它通常在该交易被插入隐含提交之前由操作方式,有可能是没有“标准方式”进行真空。

当然,这可能是可能的,即“psycopg2”有其特殊的“真空”的方法,或者一个特殊的操作模式,其中没有隐含的交易开始。

当没有这样的可能性存在,就保持一个单个选项(不改变接入层;-)):

大多数数据库有一个shell PROGRAMM访问数据库。 该方案可以与管(进入真空命令到壳体)运行该外壳程序,从而使用所述壳PROGRAMM使真空。 由于真空是一个缓慢的操作这样,外部PROGRAMM的启动会neglectible。 当然,实际的程序应前提交所有未提交的工作,否则有可能会死锁的情况 - 真空必须等到您最后一次交易的结束。



Answer 6:

不这样做 - 你不需要真空FULL。 其实,如果你运行有点最近的Postgres的版本(假设> 8.1),你甚至都不需要手动运行普通的真空。



文章来源: PostgreSQL - how to run VACUUM from code outside transaction block?