فناوری / تحلیل و راهنمای کاربردی

سایت قطع شده و PostgreSQL اتصال تازه قبول نمی‌کند

وقتی Too many connections سرویس را متوقف می‌کند، ابتدا تولید اتصال را مهار کنیم؛ سپس جلسه‌های مشکل‌دار و اندازه استخر اتصال را بررسی کنیم.

ADاردشیر دریانی··۳ دقیقه مطالعه
تصویر مفهومی ظرفیت محدود اتصال پایگاه داده و ورودی کنترل‌شده درخواست‌ها
تصویر مفهومی اختصاصی، ساخته‌شده با هوش مصنوعی؛ بازنمایی دقیق یک محصول یا معماری تجاری نیست.

موقعیت بحرانی: برنامه خطای too many connections می‌دهد. تیم برای جبران، تعداد Workerها را بیشتر می‌کند و برنامه هم بی‌وقفه تلاش مجدد می‌فرستد. در این وضعیت ممکن است خودِ اقدام جبرانی، آخرین ظرفیت آزاد پایگاه داده را مصرف کند.

اول موج اتصال را مهار کنیم

افزایش خودکار Worker و شروع Jobهای غیرضروری را موقتاً محدود کنید. اگر انتشار اخیر تعداد پردازش‌ها یا اندازه Pool را تغییر داده، همان تغییر را بررسی کنید. صفحه نگهداری یا محدودکردن ورودیِ بخش آسیب‌دیده می‌تواند فرصت تشخیص بدهد؛ هدف، توقف بازتولید فشار است، نه خاموش‌کردن بی‌دلیل تمام سرویس‌ها.

با یک اتصال مدیریتی، وضعیت را ببینیم

اگر اسلات رزروشده هنوز باقی باشد، اتصال با نقش مدیریتیِ مجاز می‌تواند ممکن باشد؛ اتصال محلی به‌تنهایی محدودیت تعداد اتصال را دور نمی‌زند. در جلسه مدیریتی PostgreSQL این پرس‌وجوهای فقط‌خواندنی را اجرا کنید:

SHOW max_connections;

SELECT application_name, usename, state, count(*) AS sessions
FROM pg_stat_activity
WHERE backend_type = 'client backend'
GROUP BY application_name, usename, state
ORDER BY sessions DESC;

این خروجی به یافتن برنامه یا حساب پرتعداد کمک می‌کند. دیدن جزئیات جلسه‌های دیگر به مجوز مناسب نیاز دارد. تعداد زیاد idle به‌تنهایی نشت اتصال را ثابت نمی‌کند؛ ممکن است Pool بزرگ باشد. وضعیت idle in transaction نیز با اتصال بیکارِ بدون تراکنش یکسان نیست.

راه‌حل را به علت وصل کنیم

برای برنامه‌ای که اتصال تولید می‌کند، سقف Pool و شمار پردازش‌ها را به ظرفیت مشترک پایگاه داده برگردانید. در سناریوی فرضی ما، بازگردانی تنظیم Worker می‌تواند از افزایش فوری max_connections منطقی‌تر باشد. افزایش این پارامتر به منابع بیشتر و راه‌اندازی مجدد سرور نیاز دارد؛ درمان خودکار نشت یا طوفان تلاش مجدد نیست.

اگر یک درخواست فعال و شناخته‌شده عامل مشکل است، لغو همان Query با pg_cancel_backend را بررسی کنید. این کار جلسه را الزاماً نمی‌بندد و اتصال بیکار را آزاد نمی‌کند. برای آزادکردن یک جلسه تأییدشده ممکن است pg_terminate_backend لازم شود؛ قطع جلسه می‌تواند تراکنش باز را Rollback کند. پیش از آن مالک کار، اثر قطع و امکان تلاش مجدد باید روشن باشد. دستور عمومی برای بستن همه جلسه‌ها، نسخه نجات نیست.

معیار پایان حادثه

یک درخواست واقعی برنامه را آزمایش کنید، کاهش خطا و پایداری تعداد اتصال‌ها را ببینید و بازگشت Jobها را تدریجی انجام دهید. اگر ظرفیت دوباره سریع پُر می‌شود، علت هنوز فعال است. پیشنهاد من برای بعد از حادثه، ثبت بودجه اتصال برای هر سرویس و داشتن Pool محدود، مالک مشخص و تأخیر مناسب در تلاش مجدد است.

تصمیم نجات‌دهنده: ابتدا شیر تولید اتصال را تنظیم کنیم؛ صرفاً مخزن را بزرگ‌تر نکنیم.

منابع: ظرفیت و اتصال‌های رزروشده PostgreSQL، مشاهده pg_stat_activity، تفاوت لغو Query و قطع Session.

تحلیل فناوری برای تصمیم‌های آگاهانه‌تر.همه نوشته‌ها →