فصل ۸: اکستنشن‌ها، اتصال به برنامه و پروژه‌ی پایانی

کلینیک خطاهای رایج PostgreSQL

پیام خطا را بخوانید؛ معمولاً دقیقاً می‌گوید چه شده

این درس فهرست مشکلاتی است که تقریباً هر تیمی دیر یا زود با آن‌ها روبه‌رو می‌شود؛ برای هرکدام علت و درمان را آورده‌ایم. اول جدول خلاصه، بعد جزئیات.

نشانهعلت رایجدرمان کوتاه
Peer authentication failed for userاتصال سوکت محلی با روش peer و نام کاربری متفاوت با کاربر سیستم‌عاملبا -h localhost وصل شوید یا خط local را scram-sha-256 کنید و reload
sorry, too many clients alreadypool نامحدود، CONN_MAX_AGE دائمی، اتصال‌های بی‌کارPgBouncer، کاهش workers، بستن اتصال‌های بی‌کار
permission denied for schema publicنسخه‌ی 15 به بعد مجوز CREATE را از PUBLIC گرفتهschema اختصاصی یا GRANT CREATE صریح
duplicate key value violates unique constraint "..._pkey" بعد از restoresequence از max(id) عقب ماندهsetval
deadlock detectedقفل ردیف‌ها با ترتیب متفاوتترتیب ثابت، retry
could not write to file ... No space left on deviceWAL انباشته از slot رهاشده یا archive شکست‌خوردهحذف slot، درست کردن archive_command
کندی تدریجی بدون تغییر کدbloat یا آمار کهنهVACUUM/ANALYZE، تنظیم autovacuum

permission denied for schema public

-- بهترین راه: schema اختصاصی برای برنامه
CREATE SCHEMA app AUTHORIZATION carpet_owner;
ALTER ROLE migrator SET search_path = app;

-- یا: مالک دیتابیس کردن نقش مالک (public از 15 مال pg_database_owner است)
ALTER DATABASE carpet OWNER TO carpet_owner;

-- یا ساده و کمتر امن
GRANT CREATE ON SCHEMA public TO migrator;

duplicate key پس از restore یا ورود دستی داده

SELECT setval(pg_get_serial_sequence('factory.orders', 'id'),
              coalesce(max(id), 0) + 1, false)
FROM factory.orders;

این حالت معمولاً وقتی پیش می‌آید که داده با id صریح وارد شده (مثلاً OVERRIDING SYSTEM VALUE یا COPY فقط داده بدون sequence). تابع pg_get_serial_sequence برای identity هم کار می‌کند.

دیسک پر از WAL

SELECT slot_name, active, wal_status,
       pg_size_pretty(pg_wal_lsn_diff(pg_current_wal_lsn(), restart_lsn)) AS retained
FROM pg_replication_slots;
SELECT failed_count, last_failed_wal, last_failed_time FROM pg_stat_archiver;

SELECT pg_drop_replication_slot('standby_old');   -- فقط اگر واقعاً دیگر لازم نیست

هرگز فایل‌های داخل pg_wal را دستی پاک نکنید؛ دیتابیس دیگر بالا نمی‌آید. علت را برطرف کنید؛ پستگرس در checkpoint بعدی خودش پاک می‌کند.

کندی تدریجی

SELECT relname, n_dead_tup, last_autovacuum, last_autoanalyze, n_mod_since_analyze
FROM pg_stat_user_tables ORDER BY n_dead_tup DESC LIMIT 10;
VACUUM (VERBOSE, ANALYZE) factory.orders;

اگر n_dead_tup بالاست و VACUUM چیزی پاک نمی‌کند (در خروجی VERBOSE عبارت «are dead but not yet removable» با عددی بزرگ)، دنبال تراکنش قدیمی، idle in transaction یا slot رهاشده بگردید (فصل ۶).

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

  • superuser_reserved_connections (پیش‌فرض ۳) چند اتصال را برای superuser نگه می‌دارد؛ حتی وقتی برنامه همه را پر کرده، می‌توانید با postgres وارد شوید و اتصال‌ها را ببندید. نسخه‌ی 16 reserved_connections و نقش pg_use_reserved_connections را هم برای نقش‌های غیر superuser آورد.
  • پیام «could not connect ... Connection refused» با «no pg_hba.conf entry» فرق دارد: اولی یعنی سرور گوش نمی‌دهد (listen_addresses، فایروال)، دومی یعنی رسیده‌اید اما pg_hba راهتان نمی‌دهد.
  • در خطای duplicate key، بخش DETAIL کلید دقیق را نشان می‌دهد (Key (id)=(1205) already exists)؛ لاگ برنامه‌ها اغلب فقط خط اول را نگه می‌دارند و همین جزئیات گم می‌شود.
  • متن کامل خطا و SQLSTATE را با \set VERBOSITY verbose در psql ببینید؛ کد SQLSTATE (مثل 23505 یا 40P01) برای مدیریت خطا در برنامه پایدارتر از متن پیام است که با زبان سرور عوض می‌شود.
  • بعد از restore یک بکاپ قدیمی، اگر برنامه خطای «column does not exist» می‌دهد، جدول django_migrations را با وضعیت واقعی جدول‌ها مقایسه کنید؛ بکاپ و کد از دو زمان متفاوت‌اند.

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