Als PostgreSQL-databasebeheerder zijn er de dagelijkse verwachtingen om back-ups te controleren, DDL-wijzigingen toe te passen, ervoor te zorgen dat de logs geen spelbrekende ERROR's bevatten en paniekoproepen te beantwoorden van ontwikkelaars wiens rapporten twee keer zo lang duren als normaal en ze heb over tien minuten een vergadering.
Zelfs met een goed begrip van de gezondheid van beheerde databases, zullen er altijd nieuwe gevallen en nieuwe problemen opduiken met betrekking tot prestaties en hoe de database "aanvoelt". Of het nu een paniekerige e-mail is of een open ticket voor "de database voelt traag", deze algemene taak kan over het algemeen worden gevolgd met een paar stappen om te controleren of er een probleem is met PostgreSQL en wat dat probleem kan zijn.
Dit is geenszins een uitputtende gids, en de stappen hoeven ook niet in een specifieke volgorde te worden uitgevoerd. Maar het is eerder een reeks eerste stappen die kunnen worden genomen om de veelvoorkomende daders snel te vinden en om nieuw inzicht te krijgen in wat het probleem kan zijn. Een ontwikkelaar weet misschien hoe de applicatie werkt en reageert, maar de databasebeheerder weet hoe de database werkt en reageert op de applicatie, en samen kan het probleem worden gevonden.
OPMERKING: De uit te voeren query's moeten worden uitgevoerd als een superuser, zoals 'postgres' of een databasegebruiker die de superuser-machtigingen heeft gekregen. Beperkte gebruikers worden geweigerd of gegevens worden weggelaten.
Stap 0 - Informatie verzamelen
Haal zoveel mogelijk informatie op van degene die zegt dat de database traag lijkt; specifieke vragen, aangesloten applicaties, tijdschema's van de trage prestaties, enz. Hoe meer informatie ze geven, hoe gemakkelijker het zal zijn om het probleem te vinden.
Stap 1 - Controleer pg_stat_activity
Het verzoek kan in veel verschillende vormen voorkomen, maar als "traagheid" het algemene probleem is, is het controleren van pg_stat_activity de eerste stap om te begrijpen wat er precies aan de hand is. De view pg_stat_activity (documentatie voor elke kolom in deze view is hier te vinden) bevat een rij voor elk serverproces / verbinding met de database vanaf een client. Er is een handvol nuttige informatie in deze weergave die kan helpen.
OPMERKING: Van pg_stat_activity is bekend dat het in de loop van de tijd van structuur verandert, waardoor de gepresenteerde gegevens worden verfijnd. Als u de kolommen zelf begrijpt, kunt u in de toekomst zo nodig dynamisch query's opstellen.
Opmerkelijke kolommen in pg_stat_activity zijn:
- query:een tekstkolom die de query toont die momenteel wordt uitgevoerd, wacht om te worden uitgevoerd of voor het laatst is uitgevoerd (afhankelijk van de status). Dit kan helpen bij het identificeren van welke zoekopdrachten/vragen die een ontwikkelaar mogelijk meldt, traag worden uitgevoerd.
- client_addr:Het IP-adres waarvan deze verbinding en query afkomstig is. Indien leeg (of Null), is het afkomstig van localhost.
- backend_start, xact_start, query_start:deze drie geven respectievelijk een tijdstempel van wanneer elk is gestart. Backend_start geeft aan wanneer de verbinding met de database tot stand is gebracht, xact_start is wanneer de huidige transactie is gestart en query_start is wanneer de huidige (of laatste) zoekopdracht is gestart.
- state:de status van de verbinding met de database. Actief betekent dat het momenteel een query uitvoert, 'inactief' betekent dat het wacht op verdere invoer van de klant, 'inactief in transactie' betekent dat het wacht op verdere invoer van de klant terwijl een openstaande transactie wordt vastgehouden. (Er zijn andere, maar hun kans is zeldzaam, raadpleeg de documentatie voor meer informatie).
- datname:de naam van de database waarmee de verbinding momenteel is verbonden. In meerdere databaseclusters kan dit helpen bij het isoleren van problematische verbindingen.
- wait_event_type en wait_event:deze kolommen zijn null wanneer een query niet wacht, maar als deze wacht, bevatten ze informatie over waarom de query wacht, en het verkennen van pg_locks kan identificeren waar deze op wacht. (PostgreSQL 9.5 en eerder heeft alleen een booleaanse kolom met de naam 'wachten', waar als u wacht, onwaar als dat niet het geval is.
1.1. Wacht / geblokkeerd?
Als er een specifieke vraag of zoekopdrachten zijn die "traag" of "hangen", controleer dan of ze wachten tot een andere vraag is voltooid. Vanwege relatievergrendeling kunnen andere query's een tabel vergrendelen en geen andere query's toegang geven tot gegevens of deze wijzigen totdat die query of transactie is voltooid.
PostgreSQL 9.5 en eerder:
SELECT * FROM pg_stat_activity WHERE waiting = TRUE;
PostgreSQL 9.6:
SELECT * FROM pg_stat_activity WHERE wait_event IS NOT NULL;
PostgreSQL 10 en hoger (?):
SELECT * FROM pg_stat_activity WHERE wait_event IS NOT NULL AND backend_type = 'client backend';
De resultaten van deze zoekopdracht laten alle verbindingen zien die momenteel wachten op een andere verbinding om vergrendelingen op een benodigde relatie vrij te geven.
Als de zoekopdracht wordt geblokkeerd door een andere verbinding, zijn er enkele manieren om erachter te komen welke dat zijn. In PostgreSQL 9.6 en later staat de functie pg_blocking_pids() de invoer toe van een proces-ID dat wordt geblokkeerd, en het zal een reeks proces-ID's retourneren die verantwoordelijk zijn voor het blokkeren ervan.
PostgreSQL 9.6 en hoger:
SELECT * FROM pg_stat_activity
WHERE pid IN (SELECT pg_blocking_pids(<pid of blocked query>));
PostgreSQL 9.5 en eerder:
SELECT blocked_locks.pid AS blocked_pid,
blocked_activity.usename AS blocked_user,
blocking_locks.pid AS blocking_pid,
blocking_activity.usename AS blocking_user,
blocked_activity.query AS blocked_statement,
blocking_activity.query AS current_statement_in_blocking_process
FROM pg_catalog.pg_locks blocked_locks
JOIN pg_catalog.pg_stat_activity blocked_activity ON blocked_activity.pid = blocked_locks.pid
JOIN pg_catalog.pg_locks blocking_locks
ON blocking_locks.locktype = blocked_locks.locktype
AND blocking_locks.DATABASE IS NOT DISTINCT FROM blocked_locks.DATABASE
AND blocking_locks.relation IS NOT DISTINCT FROM blocked_locks.relation
AND blocking_locks.page IS NOT DISTINCT FROM blocked_locks.page
AND blocking_locks.tuple IS NOT DISTINCT FROM blocked_locks.tuple
AND blocking_locks.virtualxid IS NOT DISTINCT FROM blocked_locks.virtualxid
AND blocking_locks.transactionid IS NOT DISTINCT FROM blocked_locks.transactionid
AND blocking_locks.classid IS NOT DISTINCT FROM blocked_locks.classid
AND blocking_locks.objid IS NOT DISTINCT FROM blocked_locks.objid
AND blocking_locks.objsubid IS NOT DISTINCT FROM blocked_locks.objsubid
AND blocking_locks.pid != blocked_locks.pid
JOIN pg_catalog.pg_stat_activity blocking_activity ON blocking_activity.pid = blocking_locks.pid
WHERE NOT blocked_locks.GRANTED;
(Beschikbaar via de PostgreSQL Wiki).
Deze zoekopdrachten verwijzen naar alles wat een specifieke PID blokkeert die is opgegeven. Daarmee kan een beslissing worden genomen om de blokkerende vraag of verbinding te beëindigen, of te laten lopen.
Stap 2 - Als de query's worden uitgevoerd, waarom duurt het dan zo lang?
2.1. Voert de planner zoekopdrachten efficiënt uit?
Als een query (of reeks query's) in kwestie de status 'actief' heeft, is deze daadwerkelijk actief. Als de hele query niet beschikbaar is in pg_stat_activity, haal deze dan op bij de ontwikkelaars of het postgresql-logboek en begin met het verkennen van de queryplanner.
EXPLAIN SELECT * FROM postgres_stats.table_stats t JOIN hosts h ON (t.host_id = h.host_id) WHERE logged_date >= '2018-02-01' AND logged_date < '2018-02-04' AND t.india_romeo = 569;
Nested Loop (cost=0.280..1328182.030 rows=2127135 width=335)
-> Index Scan using six on victor_oscar echo (cost=0.280..8.290 rows=1 width=71)
Index Cond: (india_romeo = 569)
-> Append (cost=0.000..1306902.390 rows=2127135 width=264)
-> Seq Scan on india_echo romeo (cost=0.000..0.000 rows=1 width=264)
Filter: ((logged_date >= '2018-02-01'::timestamp with time zone) AND (logged_date < '2018-02-04'::timestamp with time zone) AND (india_romeo = 569))
-> Seq Scan on juliet victor_echo (cost=0.000..437153.700 rows=711789 width=264)
Filter: ((logged_date >= '2018-02-01'::timestamp with time zone) AND (logged_date < '2018-02-04'::timestamp with time zone) AND (india_romeo = 569))
-> Seq Scan on india_papa quebec_bravo (cost=0.000..434936.960 rows=700197 width=264)
Filter: ((logged_date >= '2018-02-01'::timestamp with time zone) AND (logged_date < '2018-02-04'::timestamp with time zone) AND (india_romeo = 569))
-> Seq Scan on two oscar (cost=0.000..434811.720 rows=715148 width=264)
Filter: ((logged_date >= '2018-02-01'::timestamp with time zone) AND (logged_date < '2018-02-04'::timestamp with time zone) AND (india_romeo = 569))
In dit voorbeeld ziet u een queryplan voor een join met twee tabellen die ook een gepartitioneerde tabel raakt. We zijn op zoek naar iets dat ervoor kan zorgen dat de query traag is, en in dit geval doet de planner verschillende sequentiële scans op partities, wat suggereert dat ze indexen missen. Het toevoegen van indexen aan deze tabellen voor kolom 'india_romeo' zal deze zoekopdracht onmiddellijk verbeteren.
Waar u op moet letten zijn sequentiële scans, geneste lussen, dure sortering, enz. Het begrijpen van de queryplanner is cruciaal om ervoor te zorgen dat query's op de best mogelijke manier worden uitgevoerd. Officiële documentatie kan hier worden gelezen voor meer informatie.
2.2. Zijn de betrokken tabellen opgeblazen?
Als de query's nog steeds traag aanvoelen zonder dat de queryplanner naar iets voor de hand liggends wijst, is het tijd om de status van de betrokken tabellen te controleren. Zijn ze te groot? Zijn ze opgeblazen?
SELECT n_live_tup, n_dead_tup from pg_stat_user_tables where relname = ‘mytable’;
n_live_tup | n_dead_tup
------------+------------
15677 | 8275431
(1 row)
Hier zien we dat er vele malen meer dode rijen zijn dan live rijen, wat betekent dat om de juiste rijen te vinden, de engine gegevens moet doorzoeken die niet eens relevant zijn om echte gegevens te vinden. Een vacuüm / vacuüm vol op deze tafel zal de prestaties aanzienlijk verhogen.
Stap 3 - Controleer de logboeken
Als het probleem nog steeds niet kan worden gevonden, controleer dan de logs op aanwijzingen.
FATAL / ERROR-berichten:
Zoek naar berichten die problemen kunnen veroorzaken, zoals deadlocks of lange wachttijden om een lock te krijgen.
Checkpoints
Hopelijk is log_checkpoints ingeschakeld, waardoor checkpoint-informatie naar de logs wordt geschreven. Er zijn twee soorten checkpoints, getimed en aangevraagd (geforceerd). Als checkpoints worden geforceerd, moeten vuile buffers in het geheugen naar de schijf worden geschreven voordat meer query's worden verwerkt, wat een databasesysteem een algeheel gevoel van "traagheid" kan geven. Het verhogen van checkpoint_segments of max_wal_size (afhankelijk van de databaseversie) geeft de checkpointer meer ruimte om mee te werken en helpt de schrijver op de achtergrond een deel van de schrijfbelasting op zich te nemen.
Stap 4 - Wat is de gezondheid van het hostsysteem?
Als er geen aanwijzingen in de database zelf zijn, is de host zelf misschien overbelast of heeft hij problemen. Alles van een overbelast IO-kanaal tot schijf, geheugen dat overloopt om te wisselen, of zelfs een defecte schijf, geen van deze problemen zou duidelijk zijn met alles waar we eerder naar keken. Ervan uitgaande dat de database draait op een *nix-gebaseerd besturingssysteem, zijn hier een paar dingen die kunnen helpen.
4.1. Systeembelasting
Kijk met behulp van 'top' naar het belastingsgemiddelde voor de host. Als het aantal het aantal cores op het systeem benadert of overschrijdt, kunnen er simpelweg te veel gelijktijdige verbindingen zijn die de database raken, waardoor deze moet worden gecrawld om bij te blijven.
load average: 3.43, 5.25, 4.85
4.2. Systeemgeheugen en SWAP
Controleer met 'gratis' of SWAP überhaupt is gebruikt. Geheugen dat overloopt naar SWAP in een PostgreSQL-databaseomgeving is buitengewoon slecht voor de prestaties, en veel DBA's zullen SWAP zelfs elimineren van databasehosts, omdat een 'geheugen vol'-fout voor velen meer de voorkeur heeft dan een traag systeem.
Als SWAP wordt gebruikt, zal een herstart van het systeem het wissen, en het kan nodig zijn om het totale systeemgeheugen te vergroten of het geheugengebruik voor PostgreSQL opnieuw te configureren (zoals het verlagen van shared_buffers of work_mem).
[[email protected] ~]$ free -m
total used free shared buff/cache available
Mem: 7986 225 1297 12 6462 7473
Swap: 7987 2048 5939
4.3. Schijftoegang
PostgreSQL probeert veel van zijn werk in het geheugen te doen en het schrijven naar de schijf te spreiden om knelpunten te minimaliseren, maar op een overbelast systeem met veel schrijven is het gemakkelijk mogelijk om zware lees- en schrijfbewerkingen te zien, waardoor het hele systeem langzamer wordt als het inhaalt op de eisen. Snellere schijven, meer schijven en IO-kanalen zijn enkele manieren om de hoeveelheid werk die kan worden gedaan te vergroten.
Tools zoals 'iostat' of 'iotop' kunnen helpen bepalen of er een schijfknelpunt is en waar het vandaan komt.
4.4. Controleer de logboeken
Als al het andere faalt, of zelfs als dat niet het geval is, moeten logboeken altijd worden gecontroleerd om te zien of het systeem iets meldt dat niet klopt. We hebben het al gehad over het controleren van de postgresql.logs, maar de systeemlogboeken kunnen informatie geven over problemen zoals falende schijven, falend geheugen, netwerkproblemen, enz. Elk van deze problemen kan ervoor zorgen dat de database traag en onvoorspelbaar werkt, dus een goed begrip van een perfecte gezondheid kan helpen bij het vinden van deze problemen.
Download de whitepaper vandaag PostgreSQL-beheer en -automatisering met ClusterControlLees wat u moet weten om PostgreSQL te implementeren, bewaken, beheren en schalenDownload de whitepaperStap 5 - Iets is nog steeds niet logisch?
Zelfs de meest ervaren beheerders zullen iets nieuws tegenkomen dat nergens op slaat. Dat is waar de wereldwijde PostgreSQL-gemeenschap kan helpen. Net als bij stap #0 geldt:hoe duidelijker de informatie aan de gemeenschap, hoe gemakkelijker ze kunnen helpen.
5.1. PostgreSQL-mailinglijsten
Aangezien PostgreSQL is ontwikkeld en beheerd door de open source-gemeenschap, zijn er duizenden mensen die door de mailinglijsten praten om talloze onderwerpen te bespreken, waaronder functies, fouten en prestatieproblemen. De mailinglijsten zijn hier te vinden, waarbij pgsql-admin en pgsql-performance de belangrijkste zijn voor het zoeken naar hulp bij prestatieproblemen.
5.2. IRC
Freenode host verschillende PostgreSQL-kanalen met ontwikkelaars en beheerders over de hele wereld, en het is niet moeilijk om een behulpzaam persoon te vinden om op te sporen waar problemen vandaan komen. Meer informatie is te vinden op de PostgreSQL IRC-pagina.