PostgreSQL- 트랜잭션 블록 외부 코드에서 진공을 실행하는 방법은 무엇입니까?

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

문제

나는 psycopg2와 함께 Python을 사용하고 있으며 전체를 실행하려고합니다. VACUUM 수천 행을 삽입하는 일일 작업 후. 문제는 내가 실행하려고 할 때 VACUUM 내 코드 내에서 명령은 다음 오류가 발생합니다.

psycopg2.InternalError: VACUUM cannot run inside a transaction block

트랜잭션 블록 외부의 코드에서 이것을 어떻게 실행합니까?

차이가있는 경우 간단한 DB 추상화 클래스가 있는데, 그 중 일부는 컨텍스트에 대해 아래에 표시됩니다 (실행 가능, 예외 처리 및 문서가 생략하고 조정에 스패닝 한 선) :

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)
도움이 되었습니까?

해결책

더 많이 검색 한 후 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)

이 기사 (그 페이지의 끝 근처)는이 맥락에서 격리 수준에 대한 간략한 설명을 제공합니다.

다른 팁

또한 진공 청소기에서 제공 한 메시지를 받거나 다음을 사용하여 분석 할 수도 있습니다.

>> 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"

이것은 dbas ^^에 유용 할 수 있습니다

PostgreSQL의 현재 버전에서는 진공 Full이 의문의 여지가 있지만, 특정 대규모 동작이 성능을 향상 시키거나 디스크 사용을 정리할 수있는 후 '진공 분석'또는 'reindex'를 강요합니다. 이것은 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에 대한 액세스를 제공하지 않습니다.

참고 South와 함께 Django를 사용하여 마이그레이션을 수행하는 경우 다음 코드를 사용하여 A를 실행할 수 있습니다. 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이라고하자)를 실행하면 수동으로 평범한 진공을 실행할 필요조차 없습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top