PRODSuwerenna europejska platforma BaaSOtwórz Panel →

Wydajność · 9 min odczytu

Postgres max_connections bez modułu puli

Affane Daylami · Fondateur · 6 czerwca 2026

Powrót do bloga

Bez tworzenia puli przed serwerem max_connections powinien obejmować każde otwarte połączenie klienta w tym samym czasie, a nie liczbę żądań, które Postgres może efektywnie przetwarzać równolegle. Pomieszanie tych dwóch liczb jest najczęstszą przyczyną nieprawidłowego ustawienia max_connections: zbyt niska, aby przejąć obciążenie, lub zbyt wysoka w stosunku do faktycznie dostępnej pamięci.

Ten tekst w języku angielskim został wygenerowany automatycznie na podstawie francuskiego oryginału i nie był jeszcze recenzowany.
Ta strona została przetłumaczona automatycznie. Wersja angielska jest miarodajna.

W tym artykule przedstawiono formułę opublikowaną na wiki PostgreSQL do obliczenia idealnej współbieżności sprzętu (najczęściej cytowana formuła rozmiaru puli połączeń w ekosystemie), wyjaśnia, dlaczego każde połączenie kosztuje więcej niż wątek aplikacji, a następnie szczegółowo opisuje procedurę ustawiania max_connections bez zgadywania. Nasza metodologia testów porównawczych dokumentuje protokół pomiarowy używany do wszelkich oświadczeń dotyczących wydajności na tym blogu.

Najważniejsze

  • Bez łączenia, max_connections powinien obejmować wszystkie równoczesne połączenia klientów, a nie tylko te, które Postgres może efektywnie przetwarzać równolegle.
  • Formuła referencyjna wiki PostgreSQL: idealna aktywna współbieżność = (rdzenie fizyczne × 2) + wydajne dyski. Punkt wyjścia, który należy potwierdzić pomiarem, a nie sztywny limit.
  • max_connections to parametr kontekstowy postmaster: zmiana go wymaga całkowitego ponownego uruchomienia serwera, a nie prostego ponownego załadowania.
  • Każde połączenie Postgres jest oddzielnym procesem systemowym, a nie lekkim wątkiem: to właśnie sprawia, że ​​obciążenie staje się realne, gdy tylko liczba połączeń wzrośnie.
  • Zweryfikowano w kodzie: w dedykowanych klastrach Postgres Aurabase zmienia max_connections od 50 (warstwa bezpłatna) do 400 (warstwa korporacyjna) w zależności od rozmiaru klastra.
#
Diagnoza

Dlaczego połączenie Postgres kosztuje więcej niż wątek aplikacji

Postgres nie używa lekkiej puli wątków do swoich połączeń. Każde połączenie klienta uruchamia pełnoprawny proces systemowy.

Proces postmaster tworzy nowy („fork”) dla każdej próby połączenia, dedykowany tej pojedynczej sesji, aż do jej zamknięcia. Oficjalna dokumentacja projektu opisuje dokładnie ten mechanizm w rozdziale poświęconym podstawom architektury (postgresql.org/docs/current/connect-estab.html, sekcja „Connection Semantics”, dostęp 24 sierpnia 2026).

Wybór ten ma realną zaletę: awaria jednego połączenia nie wpływa na pozostałe, a każdy proces jest odizolowany od reszty serwera. Ma to również bezpośredni koszt: każde dodatkowe połączenie dodaje do harmonogramu cały proces systemu operacyjnego, z własną przestrzenią pamięci i własnym narzutem na przełączanie kontekstu dla jądra.

Co to zmienia w praktyce

Aplikacja, która otwiera 500 bezpośrednich połączeń do Postgres bez łączenia, zmusza serwer do zarządzania 500 jednoczesnymi procesami systemowymi, nawet jeśli zdecydowana większość z nich pozostaje bezczynna pomiędzy dwoma żądaniami.

#
Koszt pamięci

Co faktycznie zużywa połączenie: pamięć współdzielona i work_mem

Na pamięć wpływają dwa różne mechanizmy, a pomieszanie ich prawie zawsze prowadzi do błędnej diagnozy.

Pierwsza jest ustalona. Podczas uruchamiania Postgres rezerwuje struktury pamięci współdzielonej (blokady, tabelę procesów) o rozmiarze dostosowanym do wartości max_connections, niezależnie od tego, czy połączenia te zostaną później otwarte, czy nie. Oficjalna dokumentacja tego ustawienia wyraźnie wskazuje: zwiększenie go może wymagać większej ilości pamięci współdzielonej systemu, niż pozwala na to domyślna konfiguracja systemu operacyjnego (postgresql.org/docs/current/runtime-config-connection.html, dostęp: 24 sierpnia 2026 r.).

Drugi jest zmienny i znacznie bardziej niebezpieczny na dużą skalę: work_mem nie jest przydzielany raz na połączenie, ale raz na operację sortowania lub mieszania w planie zapytań. Oficjalna dokumentacja jasno określa tę kwestię: złożone zapytanie może uruchomić kilka z tych operacji równolegle, a kilka sesji może wykonać to samo jednocześnie, tak że faktycznie używana pamięć może być kilkukrotnie warta work_mem (postgresql.org/docs/current/runtime-config-resource.html, dostęp 24 sierpnia 2026).

Naprawdę najgorszy przypadek, o którym warto pamiętać

Nie samo max_connections × work_mem zagraża pamięci serwera. Jest to max_connections × work_mem × liczba równoczesnych operacji na zapytanie. To właśnie ten produkt wyjaśnia serwer, który się zamienia lub któremu kończy się pamięć po wzroście max_connections uważanym za nieszkodliwy.

#
Formuła

Formuła rozmiaru wiki PostgreSQL

Oficjalna wiki projektu PostgreSQL dokumentuje wzór wzorcowy do obliczania liczby aktywnych połączeń, które Twój sprzęt może wydajnie przetwarzać równolegle, a nie liczby otwartych połączeń w sumie (wiki.postgresql.org/wiki/Number_Of_Database_Connections, dostęp 24 sierpnia 2026).

Formuła

idealna aktywna współbieżność = (rdzenie fizyczne × 2) + wydajne dyski. Liczba rdzeni wyklucza hyperthreading. W nowoczesnych pamięciach SSD liczba efektywnych dysków pozostaje bliska 1, gdzie pojęcie oddzielnego dysku fizycznego („wrzeciona”) traci wiele ze swojego pierwotnego znaczenia.

Na serwerze z 8 rdzeniami fizycznymi i pamięcią SSD wzór daje (8 × 2) + 1 = 17 aktywnych połączeń, zanim przepustowość zacznie spadać. Liczba ta często zaskakuje: wydaje się niewielka w porównaniu z setkami połączeń otwieranych przez aplikację w praktyce. Jest to właśnie tematem następnego akapitu.

Liczba obliczona za pomocą wzoru mierzy współbieżność, jaką może wchłonąć procesor i dysk, a nie liczbę połączeń klienckich, które aplikacja musi otworzyć. Flota 20 procesów aplikacyjnych, każdy z własną pulą 10 połączeń, otwiera 200 jednoczesnych połączeń z Postgres, nawet jeśli tylko 17 z nich aktywnie pracuje w danym momencie. Bez modułu pulowego max_connections musi obejmować 200, a nie 17. To właśnie ta luka popycha większość architektur do dodania modułu w trybie transakcyjnym, nawet jeśli oznacza to wybranie którego z nich (zobacz nasze porównanie PgBouncer, Supavisor i PgCat).

#
Procedura

Jak zmienić max_connections (i dlaczego wymagane jest ponowne uruchomienie)

max_connections nie podlega wymianie podczas pracy. To jest parametr kontekstu postmaster: Postgres czyta go raz przy uruchomieniu, aby określić rozmiar pamięci współdzielonej. Ponowne załadowanie konfiguracji (pg_reload_conf() lub SIGHUP) nie wystarczy, należy zrestartować serwer.

Najpierw sprawdź bieżącą wartość i jej kontekst, aby potwierdzić, że konieczne będzie ponowne uruchomienie:

psqlsql
SHOW max_connections;

SELECT name, setting, context
FROM pg_settings
WHERE name = 'max_connections';

-- kontekst='postmaster' potwierdza, że ​​wymagane jest ponowne uruchomienie

Następnie zastosuj nową wartość i uruchom ponownie:

psqlsql
ALTER SYSTEM SET max_connections = '300';

-- Napisano w postgresql.auto.conf.
-- Brak efektu, dopóki Postgres nie zostanie ponownie uruchomiony.
terminalbash
# Z systemd
sudo systemctl restart postgresql

# Bez systemd, bezpośrednio z pg_ctl
pg_ctl restart -D $PGDATA -m fast
Margines, o którym wielu zapomina

max_connections zawiera domyślnie superuser_reserved_connections (domyślnie 3): te połączenia są zarezerwowane dla superużytkownika w przypadku nasycenia, nigdy nie są dostępne dla Twojej aplikacji, nawet jeśli licznik globalny nie został jeszcze osiągnięty.

#
Sprawdzone w kodzie

Jak Aurabase budżetuje max_connections w swoich klastrach Postgres

Rozmiar max_connections to nie tylko ćwiczenie teoretyczne. Oto jak Aurabase budżetuje je w zarządzanych klastrach Postgres:

100
DOMYŚLNY POSTGRES
max_connections przed jakimkolwiek strojeniem
50→400
DEDYKOWANE ŁOŻYSKA AURABASE
bezpłatne dla przedsiębiorstw, przez klaster CNPG
3
SUPERUŻYTKOWNIK ZAREZERWOWANY
superuser_reserved_connections, domyślnie Postgres

Klastry dedykowane: jeden klaster Postgres na projekt

Na tym poziomie (zobacz nasze porównanie dedykowana i współdzielona baza) każdy projekt otrzymuje własny klaster CloudNativePG i własny budżet max_connections, dostosowany do rozmiaru instancji:

bezpłatny (dedykowany)max_połączenia 501 instancja · 500 m vCPU · 512Mi
profesjonalny (domyślny)max_połączenia 2002 instancje · 1 vCPU · 2Gi
zespółmax_połączenia 3003 instancje · 2 vCPU · 3Gi
biznesmax_połączenia 4003 instancje · 2 vCPU · 4Gi

Klastry współdzielone: ​​kilka projektów organizacji, wspólny budżet

Na tej drugiej ścieżce wszystkie projekty tej samej organizacji łączą się za pośrednictwem modułu puli CNPG (PgBouncer, tryb transaction) przed współdzielonym serwerem podstawowym:

bezpłatnymax_połączenia 50max_client_conn 100max_user_connections 20
zawodowiecmax_połączenia 100max_client_conn 200max_user_connections 60
zespółmax_połączenia 200max_client_conn 400max_user_connections 150

Wszystkie projekty w organizacji łączą się za pośrednictwem udostępnionej roli aplikacji. Dlatego samo max_user_connections ogranicza całkowitą liczbę połączeń z serwerem, które ta rola może otworzyć w całym klastrze: jest to prawdziwe zabezpieczenie globalne dla klastra, a nie max_client_conn, które ogranicza jedynie połączenia klientów z samym modułem puli.

Jednak ten moduł puli obsługuje tylko ruch aplikacji SDK. Ze swojej strony PostgREST pozostaje bezpośrednio podłączony do usługi podstawowej (usługa-rw): łączenie w trybie transakcyjnym przerwałoby mechanizm przeładowywania schematu, który nasłuchuje dedykowanego kanału LISTEN o nazwie pgrst. Jego własne połączenia (2 na replikę na poziomie współdzielonym, 10 na replikę na poziomie dedykowanym) wliczają się zatem bezpośrednio do budżetu max_connections podstawowego, poza jakimkolwiek basenem, dokładnie tego rodzaju „zapomniane” połączenie, które musi obejmować krok 1 poniższej procedury.

Dane aktualnie kalibrowane, przyjęte jako takie

Kod wyraźnie dokumentuje te wspólne budżety puli jako wartości początkowe, które należy skalibrować w rzeczywistych warunkach, poprzez pomiar pg_stat_activity pod obciążeniem, a nie jako stałe wartości z opublikowanego benchmarku. Jest to ta sama dyscyplina, którą opisano w naszej metodologii testów porównawczych : zmierz przed korektą, a nie zgaduj, a potem miej nadzieję. Klastry te działają na PostgreSQL 16, wybór udokumentowany w naszym porównaniu Postgres 16 vs 17 vs 18.

#
Metoda

5-etapowa procedura określania rozmiaru max_connections bez tworzenia puli

Ta procedura nie jest zależna od żadnego konkretnego narzędzia: dotyczy dowolnego serwera Postgres, zarządzanego lub hostowanego samodzielnie.

  1. Zlicz rzeczywiste połączenia klientów. Liczba procesów aplikacji pomnożona przez wielkość ich wewnętrznej puli plus narzędzia administracyjne, replikacja i monitorowanie. To właśnie ta liczba, a nie formuła, określa minimalną wartość max_connections.
  2. Oblicz idealną współbieżność swojego sprzętu za pomocą wzoru z wiki PostgreSQL: (rdzenie fizyczne × 2) + wydajne dyski. Liczba ta wskazuje, ile z tych połączeń może faktycznie pracować równolegle bez pogarszania przepustowości.
  3. Ustaw max_connections powyżej rzeczywistej potrzeby kroku 1, z marginesem na superuser_reserved_connections i wszelkie narzędzia administracyjne, które otwierają własne połączenia poza aplikacją.
  4. Zastosuj zmianę za pomocą opcji ALTER SYSTEM SET, a następnie zrestartuj serwer. To jest parametr postmastera: proste przeładowanie nie wystarczy, jak opisano powyżej.
  5. Monitoruj pg_stat_activity w czasie. Jeśli liczba bezczynnych połączeń znacznie przekracza liczbę aktywnych połączeń, nie jest to problem max_connections: jest to sygnał, że potrzebny jest Pooler przed serwerem, a nie większa liczba.

Żądanie monitorowania z kroku 5, bezpośrednio przydatne:

psqlsql
SELECT state, count(*)
FROM pg_stat_activity
GROUP BY state
ORDER BY count(*) DESC;
#
Sygnał ostrzegawczy

Kiedy formuła już nie wystarcza: oznaki, że potrzebujesz basenowca

Trzy sygnały systematycznie powracają, gdy samo max_connections nie wystarcza, niezależnie od jego wartości.

  1. Błąd FATAL: sorry, too many clients already pojawia się w czasie szczytowego obciążenia, natomiast większość połączeń wyświetlanych przez pg_stat_activity jest w stanie bezczynności.
  2. Aplikacja działa w środowisku bezserwerowym lub z tymczasowymi procesami roboczymi (funkcje brzegowe, krótkie zadania), które otwierają i zamykają połączenia znacznie szybciej, niż został zaprojektowany w modelu przetwarzania na połączenie Postgres.
  3. Powyższa formuła i procedura zostały już zastosowane, a rzeczywiste zapotrzebowanie na połączenia klientów w dalszym ciągu przekracza to, co może przydzielić dostępna pamięć bez narażania work_mem lubshared_buffers.

W tych trzech przypadkach poprawną odpowiedzią jest prawie zawsze moduł basenowy umieszczony pomiędzy aplikacją a Postgres, a nie wyższy parametr max_connections. Nasze porównanie PgBouncer, Supavisor i PgCat szczegółowo opisuje trzy opcje, a nasz przewodnik po trybie transakcyjnym wyjaśnia najczęstszy kompromis po wprowadzeniu puli. Informacje na temat strojenia Postgres poza połączeniami można znaleźć w naszej produkcyjnej liście kontrolnej strojenia Postgres.

#
Często zadawane pytania

Często zadawane pytania

Jakie są domyślne max_connections PostgreSQL?+
100, z 3 połączeniami domyślnie zarezerwowanymi dla superużytkownika (superuser_reserved_connections). To ustawienie domyślne jest odpowiednie dla wielu aplikacji przechodzących przez moduł puli, ale szybko staje się niewystarczające bez tworzenia puli, gdy tylko każdy z procesów aplikacji otworzy własną partię połączeń.
Czy możemy zmienić max_connections bez ponownego uruchamiania PostgreSQL?+
Nie. max_connections to parametr kontekstowy postmastera: Postgres odczytuje go raz przy uruchomieniu, aby określić rozmiar pamięci współdzielonej. ALTER SYSTEM SET zapisuje nową wartość do postgresql.auto.conf, ale stosuje ją tylko pełny restart serwera; przeładowanie lub SIGHUP nie wystarczą.
Ile pamięci zużywa bezczynne połączenie PostgreSQL?+
Nie ma jednej oficjalnej liczby: zależy ona od work_mem,shared_buffers i rozszerzeń ładowanych na sesję. Udokumentowano jednak, że work_mem jest przydzielany na operację sortowania lub mieszania w zapytaniu, a nie na połączenie: dlatego pojedyncze złożone zapytanie może zużywać work_mem kilka razy w ramach jednego aktywnego połączenia.
Czy zawsze powinniśmy preferować Poolera takiego jak PgBouncer od wyższego max_connections?+
W większości przypadków tak, gdy tylko liczba rzeczywistych połączeń klientów znacznie przekroczy idealną współbieżność obliczoną za pomocą formuły wiki PostgreSQL. Pula w trybie transakcyjnym łączy niewielką liczbę połączeń fizycznych pomiędzy znacznie większą liczbą połączeń logicznych po stronie aplikacji. Zobacz nasze porównanie PgBouncer, Supavisor i PgCat, aby wybrać, który z nich.
Co dokładnie mierzy wzór (rdzenie × 2) + wydajne dyski?+
Szacuje idealną aktywną współbieżność: liczbę żądań, które procesor i dysk danego serwera mogą przetwarzać równolegle bez zmniejszania przepustowości, a nie całkowitą liczbę połączeń do otwarcia w max_connections. Jest to punkt wyjścia, który należy zweryfikować za pomocą pomiarów, udokumentowany na oficjalnej wiki projektu PostgreSQL, a nie sztywny limit.
Skąd mam wiedzieć, czy mój serwer Postgres zbliża się do limitu połączeń?+
Zapytaj o pg_stat_activity i porównaj liczbę połączeń w stanie aktywnym z liczbą połączeń w stanie bezczynności. Duża liczba bezczynnych połączeń w pobliżu limitu max_connections, bez aktywnego żądania, prawie zawsze wskazuje na potrzebę tworzenia puli, a nie potrzebę dalszego zwiększania max_connections.

GOTOWY DO WDROŻENIA?

Twój backend w pięć minut.

Karta kredytowa nie jest wymagana · 500 MB za darmo · 50 000 MAU