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

Streaming و Logical Replication

یک سرور کافی نیست

Replication دو هدف دارد: دسترس‌پذیری (اگر سرور اصلی سوخت، یکی دیگر جایش بنشیند) و تقسیم بار (گزارش‌های سنگین روی نسخه‌ی خواندنی). پستگرس دو نوع کاملاً متفاوت دارد.

Streaming (فیزیکی)Logical
چه چیزی منتقل می‌شودبایت‌های WAL؛ کپی دقیق کل کلاسترتغییرات ردیفی جدول‌های انتخابی
نسخه‌ی مقصدباید همان نسخه‌ی اصلی باشدمی‌تواند متفاوت باشد (ابزار ارتقای بی‌توقف)
مقصد قابل نوشتن؟خیر، فقط خواندنبله
DDL و sequenceبله، همه‌چیزخیر؛ باید دستی هماهنگ شود
کاربردstandby برای failover و خواندنهم‌گام‌سازی بخشی از داده، ارتقا، تجمیع

راه‌اندازی Streaming Replication

-- روی سرور اصلی
CREATE ROLE replicator WITH REPLICATION LOGIN PASSWORD 'رمز-تکثیر';
# pg_hba.conf روی سرور اصلی
hostssl  replication  replicator  10.0.0.6/32  scram-sha-256
# روی سرور standby (پوشه‌ی داده خالی)
sudo -u postgres pg_basebackup -h 10.0.0.5 -U replicator \
  -D /var/lib/postgresql/16/main -X stream -P -R -C -S standby_tehran
sudo systemctl start postgresql

-R فایل standby.signal و تنظیم primary_conninfo را خودکار می‌نویسد؛ -C -S یک replication slot می‌سازد تا سرور اصلی WAL موردنیاز standby را تا رسیدنش نگه دارد.

-- روی سرور اصلی: وضعیت و تأخیر
SELECT application_name, state, sync_state,
       pg_size_pretty(pg_wal_lsn_diff(pg_current_wal_lsn(), replay_lsn)) AS lag_bytes,
       replay_lag
FROM pg_stat_replication;

-- روی standby: ارتقا به اصلی هنگام خرابی
SELECT pg_promote();

Replication به‌طور پیش‌فرض ناهمگام است: COMMIT منتظر standby نمی‌ماند و در لحظه‌ی خرابی ممکن است چند تراکنش آخر از دست برود. با synchronous_standby_names و synchronous_commit = on هیچ تراکنش تأییدشده‌ای گم نمی‌شود، به بهای تأخیر بیشتر در هر COMMIT. برای failover خودکار از ابزاری مثل Patroni استفاده کنید؛ promote دستی ساعت سه صبح قابل اتکا نیست.

Logical Replication

-- مبدأ (wal_level = logical)
CREATE PUBLICATION pub_sales FOR TABLE factory.orders, factory.order_items, factory.customers;

-- مقصد: ساختار جدول‌ها باید از قبل وجود داشته باشد
CREATE SUBSCRIPTION sub_sales
  CONNECTION 'host=10.0.0.5 dbname=carpet user=replicator password=...'
  PUBLICATION pub_sales;

SELECT * FROM pg_stat_subscription;

نکته‌هایی که کمتر کسی می‌داند

  • replication slot رهاشده (standby که خاموش شد و فراموشش کردید) WAL را تا بی‌نهایت نگه می‌دارد و دیسک سرور اصلی را پر می‌کند؛ max_slot_wal_keep_size (نسخه‌ی 13) سقف می‌گذارد.
  • جدولی که در Logical Replication شرکت دارد برای UPDATE و DELETE به کلید اصلی (یا REPLICA IDENTITY) نیاز دارد؛ بدون آن، UPDATE روی مبدأ خطا می‌دهد.
  • بعد از سوییچ به سرور مقصد Logical، sequenceها عقب‌اند؛ قبل از باز کردن نوشتن، همه را با setval جلو ببرید.
  • کوئری طولانی روی standby ممکن است با خطای «canceling statement due to conflict with recovery» قطع شود؛ hot_standby_feedback = on این را کم می‌کند اما باعث bloat روی سرور اصلی می‌شود.
  • نسخه‌ی 17 ابزار pg_createsubscriber را آورد که یک standby فیزیکی را بدون کپی دوباره‌ی داده به subscriber منطقی تبدیل می‌کند؛ برای دیتابیس‌های بزرگ ساعت‌ها صرفه‌جویی است.

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