PostgreSQL – как запустить VACUUM из кода вне блока транзакций?

StackOverflow https://stackoverflow.com/questions/1017463

Вопрос

Я использую 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)
Это было полезно?

Решение

После дополнительных поисков я обнаружил свойство 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)

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

Другие советы

Кроме того, вы также можете получать сообщения от 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"

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

Несмотря на то, что в современных версиях 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 с 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 и SQLite, поэтому думаю, что не смогу помочь с "psycopg2".

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

  • Вне блока транзакции:Это семантически эквивалентно блоку транзакций для каждой отдельной операции SQL.
  • Внутри блока транзакций, который отмечен надписью «НАЧАТЬ ТРАНЗАКЦИЮ» и заканчивается надписью «КОНЕЦ ТРАНЗАКЦИИ».

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

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

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

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top