فصل ۷: مدیریت، امنیت و دسترس‌پذیری

PgBouncer و محدودیت‌های transaction pooling؛ ارتقا با pg_upgrade

هر اتصال یک پروسه است

در پستگرس هر اتصال یک پروسه‌ی سیستم‌عامل با چند مگابایت حافظه است. ۵۰۰ اتصال بی‌کار از چند 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 را بیشتر می‌کند.

برای ذخیره‌ی پیشرفت و شرکت در آزمون، وارد شوید — رایگان است.