PostgreSQL-如何运行的真空,从码以外的交易块?
-
06-07-2019 - |
题
我使用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。