PgBouncer 트랜잭션 레벨 풀링을 위해 SQLAlchemy에서 연결 풀링을 가장 잘 사용하는 방법은 무엇입니까?


15

SQLAlchemy를 사용하여 트랜잭션 레벨 풀링을 사용하여 PgBouncer 뒤의 PostgreSQL 데이터베이스를 쿼리합니다.

이런 종류의 설정에 가장 적합한 패턴은 무엇입니까? 을 사용하여 프로세스 당 하나의 엔진을 보유해야합니까? ConnectionPool또는 요청 당 엔진을 생성하여 각 엔진에 사용해야 NullPool합니까? 사용해야하는 다른 패턴이 있습니까?

매우 감사합니다! 더 많은 정보가 필요한지 알려 주시면 최대한 빨리 업데이트하겠습니다.

답변:


9

PGBouncer를 사용하면 NullPool을 고수하고 싶을 것입니다. 이 경우 하위 프로세스 경계를 ​​통해 소켓 연결이 수행되지 않으므로 하위 프로세스간에 단일 엔진을 공유 할 수 있습니다. 그러나이 경계에서 활성 트랜잭션이있는 세션과 같은 Connection 객체를 참조하는 것은 공유 할 수 없습니다. "요청 당 엔진"을하고 싶지는 않을 것입니다. 엔진은 처음 볼 때 특정 데이터베이스 URL에 대한 많은 정보를 축적하는 고가의 객체입니다.


4

응용 프로그램 이름 설정

많은 프로세스를 실행하려면 연결 위치를 알아야합니다. PGBouncer는이를 보이지 않게합니다 pg_stat_activity. application_name필요한 정보를 신중하게 설정하여이 문제를 해결하십시오 .

# Sets the application name for this connection in the form of
#   application-name:user@host
prog = os.path.basename(sys.argv[0]) or 'desjob'
username = pwd.getpwuid (os.getuid ()).pw_name
hostname = socket.gethostname().split(".")[0
args.setdefault('connect_args', {'application_name': "%s:%s@%s" %
    (prog, username, hostname)})
args.setdefault('isolation_level', "AUTOCOMMIT")
engine = create_engine(url, **args)

세션 선호

Engine 객체의 요청이 여러 연결을 생성하고 유지할 수 있으므로 세션을 사용하십시오. PGBouncer를 사용하면 Postgres에 연결하는 것이 그리 비싸지 않습니다. NullPoolPostgres에서 볼 수있는 유일한 연결이 실제로 사용되는 연결이되도록 항상 사용 합니다.

from sqlalchemy.pool import Pool, NullPool
engine = create_engine(uri, poolclass=NullPool)

유휴 트랜잭션 제거

PGBouncer를 사용하여 확장하려는 경우 트랜잭션을 열린 상태로 두지 않는 것이 중요합니다. 이렇게하려면을 켜야 autocommit 합니다 . 이것은 SQLAlchemy에서는 간단하지 않습니다. "autocommit"이라는 것을 설정할 수있는 세 곳이 있습니다 :

psycopg2 자동 커밋

conn = psycopg2.connect(uri)
conn.autocommit = True

SQLAlchemy는 무슨 일이 일어나고 있는지 알아야하기 때문에 안전하지 않은 것으로 추정됩니다.

세션 자동 커밋

Session = sessionmaker(bind=engine, autocommit=True)
session = Session()

이를 위해서는 신중하고 명확한 전달이 필요합니다.

session.begin()
session.execute(...)
session.rollback()

함수 호출 및 예외 나눠 때문에 대단히 어렵다 begin()commit()중첩 될 수 없습니다 :

def A():
  session.begin()
  ...
  session.rollback()

def B():
  session.begin()
  try:
      A() # error, already open

이 모드에서 psycopg2 autocommitFalse(기본값)

엔진 자동 커밋

엔진을 "AUTOCOMMIT"만들 때 엔진 격리 모드를 설정하면 기존 코드를 변경할 필요가없는 새로운 기본 동작이 설정됩니다.

engine = create_engine(uri, isolation_level="AUTOCOMMIT")

이 모드에서 psycopg2 autocommitTrue

여기서 중요한 문제는 코드 블록이 트랜잭션에 래핑되도록 보장하는 유일한 방법은 명령문을 수동으로 내보내는 것입니다.

session.execute("BEGIN")
#...
session.execute("COMMIT")
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.