Подтвердить что ты не робот

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

Я использую Python с psycopg2, и я пытаюсь запустить полный VACUUM после ежедневной операции, которая вставляет несколько тысяч строк. Проблема в том, что когда я пытаюсь запустить команду VACUUM в моем коде, я получаю следующую ошибку:

psycopg2.InternalError: VACUUM cannot run inside a transaction block

Как я могу запустить это из кода вне транзакционного блока?

Если это имеет значение, у меня есть простой класс абстракции DB, подмножество которого показано ниже для контекста (не выполняются, исключение и обработка 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)
4b9b3361

Ответ 1

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

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

Ответ 2

В то время как вакуумные версии подвержены сомнению в текущих версиях 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.

Ответ 3

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

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

эта команда распечатает список с сообщением журнала таких запросов, как "Вакуум" и "Анализ":

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"

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

Ответ 4

Обратите внимание, что если вы используете 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()

Ответ 5

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

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

  • Вне блока транзакций: это семантически эквивалентно наличию блока транзакций вокруг каждой отдельной операции SQL.
  • Внутри блока транзакций, отмеченного "BEGIN TRANSACTION" и заканчивающегося "END TRANSACTION"

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

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

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

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

Ответ 6

Не делай этого - тебе не нужен ВАКУУМ ПОЛНЫЙ. На самом деле, если вы запускаете несколько недавнюю версию Postgres (скажем, > 8.1), вам даже не нужно запускать простой VACUUM вручную.