it-swarm-eu.dev

Jak nejlépe využít sdružování připojení v SQLAlchemy pro sdružování na úrovni transakcí PgBouncer?

Použití SQLAlchemy k dotazování PostgreSQL databáze za PgBouncer, pomocí sdružování na úrovni transakcí.

Jaký je nejlepší vzor pro tento druh nastavení? Měl bych mít jeden proces na proces pomocí ConnectionPool, nebo bych měl vytvořit motor na žádost a použít NullPool pro každou z nich? Existuje úplně jiný vzor, ​​který bych měl používat?

Díky moc! Pokud budete potřebovat více informací, dejte mi vědět a aktualizuji ASAP.

16
Juan Carlos Coto

s PGBouncerem byste pravděpodobně chtěli zůstat jen s NullPool. V takovém případě budete moci sdílet jeden Engine napříč podprocesy, protože přes hranice podprocesu nebudou přenášena žádná soketová připojení. Ale nemůžete sdílet nic, co by odkazovalo na objekt připojení, jako je relace s aktivní transakcí, přes tuto hranici. Určitě byste však nechtěli dělat „engine-per-request“, ačkoliv Engine je drahý objekt, který při prvním zobrazení hromadí spoustu informací o konkrétní URL databázi.

9
zzzeek

Nastavte název aplikace

Pokud očekáváte spuštění mnoha procesů, musíte vědět, odkud se připojují. PGBouncer to učiní neviditelným pro pg_stat_activity. Vyřešte to pečlivým nastavením application_name S informacemi, které potřebujete:

# Sets the application name for this connection in the form of
#   application-name:[email protected]
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:%[email protected]%s" %
    (prog, username, hostname)})
args.setdefault('isolation_level', "AUTOCOMMIT")
engine = create_engine(url, **args)

Preferované relace

Používejte relace, protože požadavky z objektu Engine se mohou vytvářet a držet na více připojeních. Připojení k Postgresu není příliš drahé, s PGBouncer je to ještě méně. Vždy používám NullPool, takže jediná spojení, která uvidíte v Postgresu, jsou připojení, která jsou skutečně používána.

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

Eliminujte nečinné transakce

Pokud máte v úmyslu použít PGBouncer ke změně měřítka, je bezpodmínečně nutné zabránit tomu, aby transakce zůstávaly otevřené. K tomu musíte zapnout autocommiton. U SQLAlchemy to není jednoduché ... existují tři místa, kde lze nastavit něco, co se nazývá „autocommit“:

psycopg2 autocommit

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

Předpokládá se, že je nebezpečný, protože SQLAlchemy potřebuje vědět, co se děje pod ním.

Autocommit relace

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

To vyžaduje pečlivé a explicitní předání:

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

Volání funkce a zpracování výjimek je mimořádně obtížné, protože begin() a commit() nelze vnořit:

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

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

V tomto režimu se psycopg2 autocommit zdá být False (výchozí)

Autocommit

Nastavení režimu izolace motoru na "AUTOCOMMIT" Při vytváření motoru vytváří nové výchozí chování, které nemusí vyžadovat změny stávajícího kódu.

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

V tomto režimu se psycopg2 autocommit zdá být True

Hlavním problémem je, že jediným způsobem, jak zaručit, že je blok transakce zabalen do transakce, je vydat příkazy ručně:

session.execute("BEGIN")
#...
session.execute("COMMIT")
4
eradman