هر اتصال یک پروسه است
در پستگرس هر اتصال یک پروسهی سیستمعامل با چند مگابایت حافظه است. ۵۰۰ اتصال بیکار از چند worker جنگو و Celery سرور را کند میکند و با پیام «too many clients» از کار میاندازد. PgBouncer یک pool سبک بین برنامه و دیتابیس است: هزاران اتصال کلاینت را روی چند ده اتصال واقعی سوار میکند.
| حالت | اتصال سرور کی آزاد میشود | ملاحظه |
|---|---|---|
| session | وقتی کلاینت قطع شود | سازگاری کامل، صرفهجویی کم |
| transaction | پایان هر تراکنش | بیشترین صرفهجویی؛ محدودیتهای مهم دارد |
| statement | پایان هر دستور | تراکنش چنددستوری ممنوع؛ کاربرد خاص |
; /etc/pgbouncer/pgbouncer.ini
[databases]
carpet = host=127.0.0.1 port=5432 dbname=carpet
[pgbouncer]
listen_addr = 0.0.0.0
listen_port = 6432
auth_type = scram-sha-256
auth_file = /etc/pgbouncer/userlist.txt
pool_mode = transaction
default_pool_size = 20
max_client_conn = 2000
max_prepared_statements = 100
server_reset_query =
چه چیزهایی در transaction pooling خراب میشود
در این حالت، دو تراکنش پشتسرهم یک کلاینت ممکن است روی دو اتصال سرور مختلف اجرا شوند؛ پس هر چیزی که به «نشست» وابسته است قابل اتکا نیست:
SETمعمولی (بهجایشSET LOCALداخل تراکنش)- advisory lock سطح نشست،
LISTEN، جدول TEMP بیرون از تراکنش - cursorهای WITH HOLD و server-side cursor بیرون از تراکنش
- prepared statement، مگر با PgBouncer 1.21 به بعد و
max_prepared_statements
در جنگو پشت PgBouncer تراکنشی، DISABLE_SERVER_SIDE_CURSORS = True بگذارید؛ وگرنه .iterator() با خطای «cursor does not exist» میشکند.
ارتقای نسخهی اصلی با pg_upgrade
نسخههای اصلی (مثلاً 16 به 17) قالب فایل دادهی متفاوتی دارند. pg_dump/restore امن اما برای چند صد گیگابایت کند است. pg_upgrade کاتالوگ را منتقل میکند و فایلهای داده را کپی یا لینک میکند:
# اوبونتو: نسخهی جدید نصب، سپس
sudo systemctl stop postgresql
cd /tmp # pg_upgrade فایلهای لاگش را در پوشهی جاری مینویسد
sudo -u postgres /usr/lib/postgresql/17/bin/pg_upgrade \
-b /usr/lib/postgresql/16/bin -B /usr/lib/postgresql/17/bin \
-d /var/lib/postgresql/16/main -D /var/lib/postgresql/17/main \
-o '-c config_file=/etc/postgresql/16/main/postgresql.conf' \
-O '-c config_file=/etc/postgresql/17/main/postgresql.conf' \
--link --check
# اگر --check تمیز بود، همان فرمان بدون --check
sudo -u postgres /usr/lib/postgresql/17/bin/vacuumdb --all --analyze-in-stages
روی اوبونتو، pg_upgradecluster 16 main همین مراحل را با تنظیمات بستهی PGDG انجام میدهد.
نکتههایی که کمتر کسی میداند
- با
--linkارتقا چند ثانیه طول میکشد، اما بعد از اولین اجرای کلاستر جدید، کلاستر قدیمی دیگر قابل استفاده نیست؛ قبلش بکاپ بگیرید.--cloneروی فایلسیستمهای XFS و Btrfs همان سرعت را بدون این ریسک میدهد. - کلاستر جدید باید با همان encoding و locale قدیمی initdb شود؛ تفاوت locale یکی از رایجترین دلایل شکست
--checkاست. - تغییر نسخهی glibc (مشهورترینش عبور از glibc 2.28، مثلاً ارتقای اوبونتو 18.04 به 20.04) ترتیب مرتبسازی متن را عوض میکند و ایندکسهای متنی را بیصدا خراب میکند؛ بعد از ارتقای سیستمعامل REINDEX کنید یا از ICU استفاده کنید.
- PgBouncer پس از
RELOADدر کنسول مدیریتیاش (اتصال به دیتابیس مجازی pgbouncer) تنظیمات را بدون قطع اتصالها دوباره میخواند وSHOW POOLSصف انتظار کلاینتها را نشان میدهد. - اندازهی pool را بزرگ نگیرید: معمولاً چند برابر تعداد هستههای CPU کافی است؛ اتصال واقعی بیشتر فقط رقابت روی قفلها و CPU را بیشتر میکند.