PostgreSQL - как запустить VACUUM из кода вне блока транзакций? - PullRequest
31 голосов
/ 19 июня 2009

Я использую 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)

Ответы [ 6 ]

52 голосов
/ 19 июня 2009

После дополнительных поисков я обнаружил свойство isol_level объекта соединения psycopg2. Оказывается, изменение этого значения на 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)

Эта статья (ближе к концу на этой странице) дает краткое объяснение уровней изоляции в этом контексте.

4 голосов
/ 19 декабря 2012

Несмотря на то, что заполнение вакуумом сомнительно в текущих версиях 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.

4 голосов
/ 09 января 2011

Кроме того, вы также можете получить сообщения, данные Vacuum или Analyze, используя:

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

эта команда печатает список с сообщением журнала запросов, таких как Vacuum and 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"

Это может быть полезно для администраторов баз данных ^^

2 голосов
/ 15 мая 2014

Обратите внимание, что если вы используете Django с 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()
1 голос
/ 19 июня 2009

Я не знаю psycopg2 и PostgreSQL, но только apsw и SQLite, поэтому я думаю, что не могу помочь "psycopg2".

Но мне кажется, что PostgreSQL может работать аналогично SQLite, у него есть два режима работы:

  • За пределами блока транзакции. Это семантически эквивалентно наличию блока транзакции вокруг каждой отдельной операции SQL
  • Внутри блока транзакции, помеченного как «НАЧАЛО СДЕЛКИ» и заканчивающегося «КОНЕЦ СДЕЛКИ»

В этом случае проблема может быть внутри уровня доступа psycopg2. Когда он обычно работает так, что транзакции имплицитно вставляются до тех пор, пока не будет сделан коммит, не может быть «стандартного способа» создания вакуума.

Конечно, возможно, что «psycopg2» имеет свой особый «вакуумный» метод или специальный режим работы, где не запускаются неявные транзакции.

Если таких возможностей не существует, остается один единственный вариант (без изменения уровня доступа ;-)):

Большинство баз данных имеют программу оболочки для доступа к базе данных. Программа может запустить эту программу оболочки с конвейером (введя команду вакуума в оболочку), таким образом используя программу оболочки для создания вакуума. Поскольку вакуум является медленной операцией как таковой, запуск внешней программы будет игнорироваться. Конечно, реальная программа должна фиксировать всю незавершенную работу раньше, иначе может возникнуть ситуация тупиковой блокировки - вакуум должен ждать до конца вашей последней транзакции.

0 голосов
/ 19 июня 2009

Не делай этого - ВАКУУМ НЕ ТРЕБУЕТСЯ. На самом деле, если вы используете более позднюю версию Postgres (скажем,> 8.1), вам даже не нужно запускать простой VACUUM вручную.

...