41

私はpsycopg2でPythonを使用しており、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)
4

7 に答える 7

4

現在のバージョンの 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 へのアクセスを提供しません。

于 2012-12-19T15:09:25.160 に答える
4

さらに、以下を使用して、Vacuum または Analyze によって提供されるメッセージを取得することもできます。

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

このコマンドは、Vacuum や Analyse などのクエリのログ メッセージを含むリストを出力します。

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 に役立ちます ^^

于 2011-01-08T21:15:48.727 に答える
2

South で 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()
于 2014-05-15T17:18:53.957 に答える
1

私はpsycopg2とPostgreSQLを知らず、apswとSQLiteしか知らないので、「psycopg2」のヘルプを与えることはできないと思います。

しかし、PostgreSQL は SQLite と同じように動作する可能性があり、2 つの操作モードがあります。

  • トランザクション ブロックの外側: これは、すべての単一の SQL 操作の周りにトランザクション ブロックを配置することと意味的に同等です。
  • 「BEGIN TRANSACTION」でマークされ、「END TRANSACTION」で終了するトランザクション ブロック内

この場合、問題はアクセス レイヤー psycopg2 内にある可能性があります。通常、コミットが行われるまでトランザクションが暗黙的に挿入されるように動作する場合、真空を作成する「標準的な方法」はありません。

もちろん、"psycopg2" には特別な "vacuum" メソッド、または暗黙的なトランザクションが開始されない特別な操作モードがある可能性があります。

そのような可能性が存在しない場合、1 つのオプションが残ります (アクセス層を変更せずに ;-) ):

ほとんどのデータベースには、データベースにアクセスするためのシェル プログラムがあります。プログラムは、パイプを使用してこのシェル プログラムを実行し (vacuum コマンドをシェルに入力する)、シェル プログラムを使用して真空を作ることができます。バキューム自体は動作が遅いため、外部プログラムの開始は無視できます。もちろん、実際のプログラムはコミットされていないすべての作業をコミットする必要があります。そうしないと、デッドロックの状況が発生する可能性があります。バキュームは、最後のトランザクションが終了するまで待機する必要があります。

于 2009-06-19T11:59:33.097 に答える