Way*_*rts 33 python sql postgresql psycopg2 vacuum
我正在使用带有psycopg2的Python,并且我试图VACUUM在每日操作后运行一个完整的插入数千行.问题是,当我尝试VACUUM在我的代码中运行命令时,我收到以下错误:
psycopg2.InternalError: VACUUM cannot run inside a transaction block
Run Code Online (Sandbox Code Playgroud)
如何从事务块外部的代码运行它?
如果它有所不同,我有一个简单的DB抽象类,下面显示了一个子集用于上下文(不是runnable,省略了异常处理和docstrings以及进行了行跨越调整):
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)
Run Code Online (Sandbox Code Playgroud)
Way*_*rts 55
经过更多搜索后,我发现了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)
Run Code Online (Sandbox Code Playgroud)
本文(接近该页末尾)提供了此上下文中隔离级别的简要说明.
对于尝试了有关此问题的所有建议但没有成功的其他人,您可能会遭受与我相同的命运:我在一次execute()调用中有 2 个(或更多)SQL 语句。事实证明,Postgres 本身会在第一个语句之后重置所有自动提交/隔离(用 分隔;)。我终于在这里找到了解决方案:https ://github.com/psycopg/psycopg2/issues/1201
所以不要做这样的事情:
cursor.execute("SELECT 1; VACUUM FULL")
Run Code Online (Sandbox Code Playgroud)
相反,做:
cursor.execute("SELECT 1")
cursor.execute("VACUUM FULL")
Run Code Online (Sandbox Code Playgroud)
此外,您还可以使用以下命令获取 Vacuum 或 Analytics 给出的消息:
\n\n>> print conn.notices #conn is the connection object\nRun Code Online (Sandbox Code Playgroud)\n\n此命令打印一个列表,其中包含 Vacuum 和 Analyse 等查询的日志消息:
\n\nINFO: "usuario": processados 1 de 1 p\xc3\xa1ginas, contendo 7 registros vigentes e 0 registros n\xc3\xa3o vigentes; 7 registros amostrados, 7 registros totais estimados \nINFO: analisando "public.usuario"\nRun Code Online (Sandbox Code Playgroud)\n\n这对 DBA 很有用 ^^
\n虽然在当前版本的 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)
Run Code Online (Sandbox Code Playgroud)
不幸的是,django 提供的连接代理不提供对 set_isolation_level 的访问。
| 归档时间: |
|
| 查看次数: |
16251 次 |
| 最近记录: |