PostgreSQL kļūda "sorry, too many clients already" nozīmē, ka visi savienojumu sloti serverī ir aizņemti, tāpēc serveris jauno savienojumu atsaka. Parasti serveris nemaz nav pārslogots: lielākā daļa šo savienojumu vienkārši dīkst. Ātrais risinājums ir atbrīvot slotus. Īstais risinājums ir panākt, lai lietotne neatver vairāk savienojumu, nekā datubāze spēj izmantot.
Jūs redzēsiet vienu no šiem diviem ziņojumiem, bieži abus:
FATAL: sorry, too many clients already
FATAL: remaining connection slots are reserved for roles with the SUPERUSER attribute
Abi ir FATAL ar SQLSTATE 53300 (too_many_connections). Pirmais nāk no proc.c, kad brīvu slotu vairs nav vispār. Otrais nāk no postinit.c, kad vienīgie brīvie sloti ir rezervēti; PostgreSQL 16+ ar iestatītu reserved_connections kāds variants nosauc lomu pg_use_reserved_connections. Pirms PostgreSQL 16 otrais ziņojums skanēja "remaining connection slots are reserved for non-replication superuser connections". Ja redzat ziņojumu, kurā nosaukta loma vai datubāze, "too many connections for role" vai "too many connections for database", jūs esat sasnieguši lomas vai datubāzes CONNECTION LIMIT, nevis servera limitu (miscinit.c).
Kā limits patiesībā darbojas
No savienojumu iestatījumu dokumentācijas:
- max_connections noklusējums parasti ir 100, iespējams, mazāk, ja initdb konstatēja, ka kodols to neatbalsta. To var mainīt tikai ar servera restartu, un replikai jābūt tādai pašai vai lielākai vērtībai kā tās primārajam serverim.
- superuser_reserved_connections noklusējums ir 3. Kad brīvi ir tikai šie sloti, pieslēgties drīkst tikai superlietotāji. Ar noklusējumiem parastās lomas tiek atteiktas pie 97 savienojumiem.
- reserved_connections (PostgreSQL 16+, noklusējums 0) rezervē papildu slotus lomām ar
pg_use_reserved_connectionsprivilēģijām, piemēram, uzraudzībai.
Tātad ziņojums kaut ko pasaka. "Remaining slots are reserved" nozīmē, ka parastajām lomām sloti beigušies, bet jūs kā superlietotājs vēl varat ieiet un paskatīties. "Too many clients already" nozīmē, ka beigusies arī rezerve. No mūsu pieredzes, tas bieži norāda uz lietotni, kas pieslēdzas kā superlietotājs postgres un kopā ar visu pārējo apēd arī avārijas rezervi.
1. solis: paskatieties, pirms restartējat
Pieslēdzieties kā superlietotājs, kamēr rezerve vēl ir, un paskatieties, kas aizņem slotus:
-- kas aizņem slotus? (pieslēdzieties kā superlietotājs: rezerve ir jums)
SELECT usename, application_name, client_addr, state, count(*)
FROM pg_stat_activity
WHERE backend_type = 'client backend'
GROUP BY 1, 2, 3, 4
ORDER BY count(*) DESC
LIMIT 20;
SHOW max_connections;
SHOW superuser_reserved_connections;
Parasti aina kļūst skaidra minūtes laikā:
- Simtiem
idlesesiju no lietotņu serveriem. Katrai instancei vai darbiniekam ir savs pūls, un kopsumma pārsniedz servera atļauto. Desmit podi ar pūlu 20 katrā jau prasa 200 slotus. - Daudz
idle in transactionsesiju. Kods atver transakciju un to nepabeidz. Tās tur slēdzenes un bloķē arī VACUUM: skatiet mūsu rakstu par idle in transaction. - Daudz
activesesiju, kas gaida slēdzenes vai I/O. Datubāze tiešām ir lēna, savienojumi uzkrājas, kamēr vaicājumi gaida, un lietotne atver vēl vairāk. Šeit savienojuma kļūda ir simptoms; labojiet lēno vaicājumu vai slēdzeni. - Viens
client_addrvaiapplication_namear krietni vairāk sesijām nekā pārējiem. Noplūde vienā servisā, nevaldāms cron uzdevums vai BI rīks.
2. solis: droši atbrīvojiet slotus
PostgreSQL restarts atbrīvo visus slotus, bet tas arī nogalina katru darbojošos transakciju, un, ja cēlonis ir lietotnē, sloti minūšu laikā piepildās atkal. Pareizo sesiju beigšana ir saudzīgāka:
-- atbrīvojiet slotus tagad: beidziet sesijas, kas transakcijā dīkst ilgāk par 10 minūtēm
SELECT pid, usename, application_name, now() - state_change AS idle_for,
pg_terminate_backend(pid)
FROM pg_stat_activity
WHERE state = 'idle in transaction'
AND now() - state_change > interval '10 minutes';
pg_terminate_backend darbojas superlietotājiem, lomām ar pg_signal_backend privilēģijām un sesijas lomas dalībniekiem, taču superlietotāja sesiju var beigt tikai superlietotājs (servera signālu funkcijas). Katra beigtā transakcija tiek atritināta, tāpēc sāciet ar acīmredzami aizmirstām sesijām, nevis aktīvām.
Nesteidzieties ar max_connections = 1000. Katrs savienojums ir atsevišķs servera process, un PostgreSQL daļu koplietojamās atmiņas izmēro pēc max_connections. No mūsu pieredzes, serveris ar tūkstošiem pārsvarā dīkstāvē esošu savienojumu zem slodzes parasti kļūst lēnāks, nevis ātrāks, jo pārāk daudz aktīvu vaicājumu konkurē par to pašu CPU un slēdzenēm. Mērena limita palielināšana ir labi, ja serverim ir rezerve. Desmitkārtīga palielināšana tikai pārceļ dīkstāvi.
3. solis: novērsiet cēloni
- Ielieciet priekšā pūleri. PgBouncer transakciju režīmā ļauj tūkstošiem klientu savienojumu koplietot dažus desmitus servera savienojumu. Tas ir standarta risinājums daudzām lietotņu instancēm, serverless funkcijām un PHP darbiniekiem. Uzstādīšana un slazdi ir mūsu PgBouncer ceļvedī.
- Apzināti izmēriet lietotņu pūlus. Saskaitiet maksimālo pūla izmēru visās instancēs, darbiniekos un cron uzdevumos, arī izvietošanas laikā, kad vienlaikus strādā vecie un jaunie podi, un turiet kopsummu zem max_connections mīnus rezerve.
- Ierobežojiet lomas un datubāzes, ne tikai serveri.
CONNECTION LIMITlomai vai datubāzei neļauj vienam servisam vai vienam analītiķim paņemt visus slotus. - Aizveriet aizmirstas sesijas automātiski.
idle_in_transaction_session_timeoutbeidz sesijas, kas dīkst transakcijas iekšienē.idle_session_timeout(PostgreSQL 14+) beidz dīkstāvē esošas sesijas ārpus transakcijas. Abu noklusējums ir 0, kas nozīmē izslēgts (klienta iestatījumi). Dokumentācija brīdina nelietotidle_session_timeoutsavienojumiem caur pūleri vai citu starpprogrammatūru, tāpēc iestatiet to pa lomām, interaktīviem lietotājiem. - Atstājiet durvis vaļā sev. Nekad neļaujiet lietotnēm pieslēgties kā superlietotājam. PostgreSQL 16+ piešķiriet uzraudzībai savu rezervi ar
reserved_connections, lai brīdinājumi strādātu arī tad, kad parastās lomas ir izslēgtas.
-- ierobežojiet trokšņaino kaimiņu, nevis visu serveri
ALTER ROLE reporting CONNECTION LIMIT 20;
ALTER DATABASE analytics CONNECTION LIMIT 50;
-- aizveriet aizmirstas sesijas automātiski, pa lomām
ALTER ROLE app SET idle_in_transaction_session_timeout = '5min';
ALTER ROLE analyst SET idle_session_timeout = '30min'; -- PostgreSQL 14+
-- PostgreSQL 16+: rezerve uzraudzības un ops lomām
-- postgresql.conf: reserved_connections = 5 (vajag restartu)
GRANT pg_use_reserved_connections TO monitoring;
Visbeidzot, brīdiniet pirms sienas: sekojiet klientu procesu skaitam attiecībā pret max_connections un brīdiniet pie aptuveni 80%. Tad nākamais savienojumu pīķis būs pieteikums, nevis dīkstāve.
Galvenās atziņas
- "sorry, too many clients already" nozīmē, ka aizņemti visi sloti; "remaining connection slots are reserved" nozīmē, ka palikusi tikai superlietotāja rezerve.
- Pieslēdzieties kā superlietotājs un grupējiet
pg_stat_activitypēc lietotāja, lietotnes, adreses un stāvokļa, pirms kaut ko restartējat. - Atbrīvojiet slotus, beidzot aizmirstas
idle in transactionsesijas arpg_terminate_backend. - max_connections noklusējums ir aptuveni 100, un tā maiņai vajag restartu; desmitkārtīga palielināšana nav risinājums.
- Paliekošs risinājums ir pūleris, izmērīti lietotņu pūli, lomu limiti un dīkstāves taimauti.
- Neļaujiet lietotnēm izmantot superlietotāja kontus, lai avārijas rezerve paliktu jums.