PgBouncer transaction pool штеди везе — али ломи стање сесије

|Аутор: Уредништво QUASA|6 мин читања
PgBouncer transaction pool штеди везе — али ломи стање сесије

PgBouncer у transaction режиму враћа PostgreSQL серверску везу у скуп чим се трансакција заврши, па иста веза може да послужи другом клијенту. У session режиму задржава је за клијента до прекида његове везе, како објашњава PgBouncer мапа режима и компатибилности. Дељење зато највише користи апликацији са много отворених клијентских веза и кратким трансакцијама.

Цена тог избора је прекид везе између клијента и исте PostgreSQL серверске сесије после COMMIT-а. Ако наредни упит зависи од раније постављеног параметра, регистрације за обавештења, привремене табеле, сесијске блокаде или SQL припремљеног упита, задржите session режим док ту зависност не уклоните. Када сав потребан контекст настаје и завршава се у истој трансакцији, transaction режим је кандидат за пробу.

Када дељење веза заиста помаже

Предност transaction режима расте када клијентске везе дуго остају отворене, а између њихових кратких трансакција има пауза. Серверска веза тада не чека клијента који тренутно не ради ништа; PgBouncer може да је додели следећој трансакцији. Зато број истовремено отворених клијентских веза сам по себи не говори колики је скуп серверских веза потребан. Важније је колико трансакција истовремено заузима сервер и колико дуго трају.

Отворена трансакција задржава додељену серверску везу чак и када клијент између наредби мирује у стању „idle in transaction“. Дуге трансакције зато смањују простор за поновну употребу веза. Корист зависи и од распореда оптерећења по базама и корисницима: PgBouncer за њих формира одвојене скупове, па слободна веза у једном скупу не мора да помогне клијенту који чека у другом. Промена режима не замењује одређивање одговарајуће величине сваког скупа.

Које зависности траже сталну сесију

Привремена PostgreSQL табела везана за сесију остаје на једној серверској вези, док следећа PgBouncer трансакција може добити другу.

Проверите наредбе које шаље апликација, укључујући рад драјвера, ORM-а, миграција и позадинских радника. Одлучујуће питање за сваку функцију гласи: да ли резултат мора да остане доступан истом клијенту после завршетка трансакције?

  • Да ли апликација извршава обичан SET или RESET и очекује да промена важи у следећој трансакцији? Не ослањајте се на то без провере праћења баш тог параметра у вашој конфигурацији. Ако је вредност потребна само током једне експлицитне трансакције, правило PostgreSQL за SET LOCAL ограничава њено важење до COMMIT-а или ROLLBACK-а; све зависне наредбе морају остати у тој трансакцији.
  • Да ли клијент извршава LISTEN па између трансакција чека обавештења? Регистрација припада серверској сесији, па том клијенту треба session режим. Клијент који само шаље NOTIFY нема исту зависност.
  • Да ли привремена табела мора да преживи COMMIT, чак и ако се њени редови тада бришу? Њен идентитет остаје везан за серверску сесију. Transaction режим одговара табели са ON COMMIT DROP само када се она направи, употреби и уклони у оквиру исте трансакције.
  • Да ли код узима pg_advisory_lock и касније позива pg_advisory_unlock? Та блокада припада сесији и захтева стабилну серверску везу. Ако заштита треба да траје само док траје трансакција, одговарајућа могућност је pg_advisory_xact_lock, који се ослобађа њеним завршетком.
  • Да ли апликација шаље SQL PREPARE, EXECUTE и DEALLOCATE кроз више трансакција или драјвер користи именоване припремљене упите PostgreSQL протокола? SQL наредбе зависе од сесије. Протоколске припремљене упите PgBouncer може да прати у transaction режиму када је max_prepared_statements већи од нуле; механизми нису међусобно заменљиви.

Исти критеријум важи за друге ресурсе које апликација оставља на серверу после COMMIT-а, попут курсора који остаје отворен. Ако је серверска сесија део логике рада, њено случајно поновно добијање у transaction режиму није гаранција: следећу трансакцију може преузети друга веза.

Минимална конфигурација за оба режима

У одељку [pgbouncer] линија pool_mode = session задржава серверску везу до одјаве клијента; то је и подразумевани режим. За део апликације који не зависи од стања између трансакција, минимална промена је pool_mode = transaction. Конфигурација PgBouncer допушта и pool_mode за појединачну базу или корисника, па се различите путање апликације могу усмерити у различите скупове.

За такву поделу није довољно променити само једну глобалну линију ако исти улаз користе и клијенти којима треба session режим. Дефинишите одвојене улазе у одељку [databases] или раздвојите кориснике, па за сваки задајте одговарајући pool_mode. Тако радник који слуша обавештења може задржати сесију, док кратки захтеви који користе само стање текуће трансакције деле серверске везе.

Посебно проверите SET параметре: PgBouncer прати само оне промене које PostgreSQL пријављује и које конфигурација дозвољава да прати. То зависи и од верзије PostgreSQL-а; на пример, пријављивање промене search_path разликује се између верзија. Непраћена промена може остати на серверској вези коју затим добије други клијент. server_reset_query се у transaction режиму подразумевано не извршава при враћању везе у скуп, па није замена за уклањање зависности од сесије. За протоколске припремљене упите проверите стварну вредност max_prepared_statements и понашање драјвера; то подешавање не решава SQL PREPARE.

Провере пре промене у продукцији

Провера pg_backend_pid() између трансакција открива да PgBouncer може доделити другу PostgreSQL серверску сесију.

Пробу изведите кроз исти PgBouncer улаз и са истим подешавањима драјвера које ће користити апликација. Укључите више истовремених клијената: један успешан пролаз може значити само да је клијент случајно поново добио исту серверску везу. Изоловани SQL пример допуните стварним путањама кода, посебно онима у којима драјвер сам припрема упите.

  1. У истој клијентској вези позовите SELECT pg_backend_pid(); у одвојеним трансакцијама док и други клијенти раде. Различити резултати показују промену PostgreSQL серверске сесије. Исти резултат у неколико покушаја не доказује да ће сесија остати иста.
  2. За вредност ограничену на трансакцију извршите BEGIN; SET LOCAL search_path TO pg_catalog; SHOW search_path; COMMIT;. Затим поново позовите SHOW search_path;. Вредност постављена са SET LOCAL треба да важи за упите пре COMMIT-а, а да престане да важи по његовом завршетку; забележите и почетну вредност ради поређења.
  3. За привремену табелу испробајте BEGIN; CREATE TEMP TABLE pool_probe (id integer) ON COMMIT DROP; INSERT INTO pool_probe VALUES (1); SELECT count(*) FROM pool_probe; COMMIT;. Ако стварни код табелу чита тек после COMMIT-а, та путања тражи session режим или измену животног циклуса табеле.
  4. Проверите да ли SQL PREPARE и каснији EXECUTE прелазе границу трансакције. Одвојено испробајте припремљене упите које ствара драјвер. За клијенте који користе LISTEN или сесијску advisory блокаду проверите где се регистрација или блокада успоставља, а где се касније користи или ослобађа.

Transaction режим примените на путање чији рад остаје исправан и када узастопне трансакције добију различите серверске сесије. Путање којима су LISTEN, привремена табела или сесијска блокада потребни после COMMIT-а усмерите на session режим; ту је трајна додела везе услов исправног рада.

Прочитајте и:

Подели:

Претплатите се на наш билтен

Добијајте најновије вести о Web3, AI-у и криптовалутама директно у пријемно сандуче.

0