Установите имя приложения
Если вы ожидаете запуска многих процессов, вам нужно знать, откуда они подключаются. 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)
Предпочитайте сессии
Используйте Sessions, так как запросы от объекта Engine могут порождаться и удерживаться для нескольких соединений. Подключение к Postgres не очень дорого, с PGBouncer - еще меньше. Я всегда использовал бы NullPool
так, чтобы единственными соединениями, которые вы увидите в Postgres, были соединения, которые фактически используются.
from sqlalchemy.pool import Pool, NullPool
engine = create_engine(uri, poolclass=NullPool)
Устранить пустые транзакции
Если вы намерены использовать PGBouncer для масштабирования, обязательно избегайте оставлять транзакции открытыми. Для этого вам необходимо обратиться autocommit
в . Это не просто с SQLAlchemy ... есть три места, где можно установить что-то под названием "autocommit":
psycopg2 autocommit
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 autocommit
выглядит False
(по умолчанию)
Автокоммит двигателя
Установка режима изоляции Engine "AUTOCOMMIT"
при создании двигателя устанавливает новое поведение по умолчанию, которое может не требовать изменений в существующем коде.
engine = create_engine(uri, isolation_level="AUTOCOMMIT")
В этом режиме psycopg2 autocommit
оказываетсяTrue
Основная проблема здесь состоит в том, что единственный способ гарантировать, что блок кода обернут в транзакцию, состоит в том, чтобы выдать операторы вручную:
session.execute("BEGIN")
#...
session.execute("COMMIT")