Som en PostgreSQL-databasadministratör finns det vardagliga förväntningar på att kontrollera säkerhetskopior, tillämpa DDL-ändringar, se till att loggarna inte har några spelbrytande FEL och svara på paniksamtal från utvecklare vars rapporter körs dubbelt så länge som normalt och de ha ett möte om tio minuter.
Även med en god förståelse för tillståndet hos hanterade databaser kommer det alltid att dyka upp nya fall och nya frågor som rör prestanda och hur databasen "känns". Oavsett om det är ett e-postmeddelande med panik, eller en öppen biljett för "databasen känns långsam", kan denna vanliga uppgift i allmänhet följas med några steg för att kontrollera om det finns ett problem med PostgreSQL och vad det kan vara.
Detta är inte på något sätt en uttömmande guide, och stegen behöver inte heller göras i någon specifik ordning. Men det är snarare en uppsättning inledande steg som kan tas för att hjälpa till att hitta vanliga förövare snabbt, samt få ny insikt om vad problemet kan vara. En utvecklare kanske vet hur applikationen agerar och reagerar, men databasadministratören vet hur databasen agerar och reagerar på applikationen, och tillsammans kan problemet hittas.
OBS: Frågorna som ska köras bör göras som en superanvändare, till exempel "postgres" eller vilken databasanvändare som helst som beviljats superanvändarbehörigheter. Begränsade användare kommer antingen att nekas eller få data utelämnad.
Steg 0 – Informationsinsamling
Få så mycket information som möjligt från den som säger att databasen verkar långsam; specifika frågor, anslutna applikationer, tidsramar för prestandans långsamhet, etc. Ju mer information de ger desto lättare blir det att hitta problemet.
Steg 1 - Kontrollera pg_stat_activity
Begäran kan komma i många olika former, men om "långsamhet" är det allmänna problemet är att kontrollera pg_stat_activity det första steget för att förstå precis vad som händer. Vyn pg_stat_activity (dokumentation för varje kolumn i denna vy finns här) innehåller en rad för varje serverprocess/anslutning till databasen från en klient. Det finns en handfull användbar information i den här vyn som kan hjälpa.
OBS: pg_stat_activity har varit känt för att ändra struktur över tid, förfina data den presenterar. Förståelse av själva kolumnerna kommer att hjälpa till att skapa frågor dynamiskt efter behov i framtiden.
Viktiga kolumner i pg_stat_activity är:
- fråga:en textkolumn som visar frågan som för närvarande körs, väntar på att köras eller senast kördes (beroende på tillstånd). Detta kan hjälpa till att identifiera vilka frågor en utvecklare kan rapportera som körs långsamt.
- client_addr:IP-adressen som den här anslutningen och frågan kommer från. Om den är tom (eller Null), kommer den från localhost.
- backend_start, xact_start, query_start:Dessa tre ger en tidsstämpel för när var och en startade respektive. Backend_start representerar när anslutningen till databasen upprättades, xact_start är när den aktuella transaktionen startade och query_start är när den aktuella (eller senaste) frågan startade.
- tillstånd:Tillståndet för anslutningen till databasen. Aktiv betyder att den för närvarande kör en fråga, "tomgång" betyder att den väntar på ytterligare input från klienten, "tom i transaktion" betyder att den väntar på ytterligare input från klienten medan den håller en öppen transaktion. (Det finns andra, men deras sannolikhet är sällsynt, se dokumentationen för mer information).
- datname:Namnet på databasen som anslutningen för närvarande är ansluten till. I flera databaskluster kan detta hjälpa till att isolera problematiska anslutningar.
- wait_event_type och wait_event:Dessa kolumner kommer att vara null när en fråga inte väntar, men om den väntar kommer de att innehålla information om varför frågan väntar, och att utforska pg_locks kan identifiera vad den väntar på. (PostgreSQL 9.5 och tidigare har bara en boolesk kolumn som heter "väntar", sant om väntar, falskt om inte.
1.1. Väntar/blockeras frågan?
Om det finns en specifik fråga eller frågor som är "långsamma" eller "hängde", kontrollera om de väntar på att en annan fråga ska slutföras. På grund av relationslåsning kan andra frågor låsa en tabell och inte låta några andra frågor komma åt eller ändra data förrän den frågan eller transaktionen är klar.
PostgreSQL 9.5 och tidigare:
SELECT * FROM pg_stat_activity WHERE waiting = TRUE;
PostgreSQL 9.6:
SELECT * FROM pg_stat_activity WHERE wait_event IS NOT NULL;
PostgreSQL 10 och senare (?):
SELECT * FROM pg_stat_activity WHERE wait_event IS NOT NULL AND backend_type = 'client backend';
Resultaten av denna fråga kommer att visa alla anslutningar som för närvarande väntar på en annan anslutning för att släppa lås på en relation som behövs.
Om frågan blockeras av en annan anslutning finns det några sätt att ta reda på vad de är. I PostgreSQL 9.6 och senare tillåter funktionen pg_blocking_pids() inmatning av ett process-ID som blockeras, och det kommer att returnera en rad process-ID:n som är ansvariga för att blockera det.
PostgreSQL 9.6 och senare:
SELECT * FROM pg_stat_activity
WHERE pid IN (SELECT pg_blocking_pids(<pid of blocked query>));
PostgreSQL 9.5 och tidigare:
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;
(Tillgänglig från PostgreSQL Wiki).
Dessa frågor kommer att peka på vad som än blockerar en specifik PID som tillhandahålls. Med det kan ett beslut tas om att stänga av blockeringsfrågan eller anslutningen, eller låta den köras.
Steg 2 – Om frågorna körs, varför tar de så lång tid?
2.1. Kör planeraren frågor effektivt?
Om en fråga (eller en uppsättning frågor) i fråga har statusen "aktiv", så körs den faktiskt. Om hela frågan inte är tillgänglig i pg_stat_activity, hämta den från utvecklarna eller postgresql-loggen och börja utforska frågeplaneraren.
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))
Det här exemplet visar en frågeplan för en koppling med två tabeller som också träffar en partitionerad tabell. Vi letar efter allt som kan göra att frågan blir långsam, och i det här fallet gör planeraren flera sekventiella skanningar på partitioner, vilket tyder på att de saknar index. Om du lägger till index i dessa tabeller för kolumnen 'india_romeo' kommer denna fråga omedelbart att förbättras.
Saker att leta efter är sekventiella skanningar, kapslade slingor, dyr sortering, etc. Att förstå frågeplaneraren är avgörande för att se till att frågor fungerar på bästa sätt, officiell dokumentation kan läsas för mer information här.
2.2. Är de inblandade tabellerna uppsvällda?
Om frågorna fortfarande känns långsamma utan att frågeplaneraren pekar på något uppenbart, är det dags att kontrollera tillståndet för de inblandade tabellerna. Är de för stora? Är de uppsvällda?
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)
Här ser vi att det finns många gånger fler döda rader än levande rader, vilket innebär att för att hitta rätt rader måste motorn sålla igenom data som inte ens är relevant för att hitta riktig data. Ett vakuum/vakuum fullt på detta bord kommer att öka prestandan avsevärt.
Steg 3 - Kontrollera loggarna
Om problemet fortfarande inte kan hittas, kontrollera loggarna för ledtrådar.
FATALA / FEL-meddelanden:
Leta efter meddelanden som kan orsaka problem, som dödläge eller långa väntetider för att få ett lås.
Kontrollpunkter
Förhoppningsvis är log_checkpoints inställd på på, vilket kommer att skriva checkpointinformation till loggarna. Det finns två typer av kontrollpunkter, tidsinställda och begärda (tvingade). Om kontrollpunkter tvingas fram måste smutsiga buffertar i minnet skrivas till disken innan fler frågor bearbetas, vilket kan ge ett databassystem en övergripande känsla av "långsamhet". Att öka checkpoint_segments eller max_wal_size (beroende på databasversion) kommer att ge checkpointern mer utrymme att arbeta med, samt hjälpa bakgrundsskrivaren att ta en del av skrivbelastningen.
Steg 4 – Hur ser värdsystemet ut?
Om det inte finns några ledtrådar i själva databasen, kanske själva värden är överbelastad eller har problem. Allt från en överbelastad IO-kanal till disk, överfyllt minne för att byta, eller till och med en felaktig enhet, inget av dessa problem skulle vara uppenbart med något vi tittade på tidigare. Förutsatt att databasen körs på ett *nix-baserat operativsystem, här är några saker som kan hjälpa.
4.1. Systembelastning
Använd "top" och titta på belastningsgenomsnittet för värden. Om antalet närmar sig eller överstiger antalet kärnor i systemet, kan det helt enkelt vara för många samtidiga anslutningar som träffar databasen och för den till en genomsökning för att hinna ikapp.
load average: 3.43, 5.25, 4.85
4.2. Systemminne och SWAP
Använd "gratis", kontrollera om SWAP har använts överhuvudtaget. Minnet som flödar över till SWAP i en PostgreSQL-databasmiljö är extremt dåligt för prestandan, och många DBA:er kommer till och med att eliminera SWAP från databasvärdar, eftersom ett fel som är slut på minnet är mer att föredra än ett trögt system för många.
Om SWAP används kommer en omstart av systemet att rensa bort det, och att öka det totala systemminnet eller omkonfigurera minnesanvändningen för PostgreSQL (som att sänka shared_buffers eller work_mem) kan vara på sin plats.
[[email protected] ~]$ free -m
total used free shared buff/cache available
Mem: 7986 225 1297 12 6462 7473
Swap: 7987 2048 5939
4.3. Diskåtkomst
PostgreSQL försöker göra mycket av sitt arbete i minnet och sprida skrivning till disk för att minimera flaskhalsar, men på ett överbelastat system med tungt skrivande är det lätt möjligt att se tunga läsningar och skrivningar gör att hela systemet blir långsammare när det kommer ikapp på kraven. Snabbare diskar, fler diskar och IO-kanaler är några sätt att öka mängden arbete som kan göras.
Verktyg som "iostat" eller "iotop" kan hjälpa till att fastställa om det finns en diskflaskhals och var den kan komma ifrån.
4.4. Kontrollera loggarna
Om allt annat misslyckas, eller även om inte, bör loggar alltid kontrolleras för att se om systemet rapporterar något som inte är rätt. Vi har redan diskuterat att kontrollera postgresql.logs, men systemloggarna kan ge information om problem som diskar som inte fungerar, minnesfel, nätverksproblem etc. Alla dessa problem kan få databasen att agera långsamt och oförutsägbart, så en god förståelse av perfekt hälsa kan hjälpa till att hitta dessa problem.
Ladda ner Whitepaper Today PostgreSQL Management &Automation med ClusterControlLäs om vad du behöver veta för att distribuera, övervaka, hantera och skala PostgreSQLDladda WhitepaperSteg 5 – Något som fortfarande inte är meningsfullt?
Även de mest erfarna administratörerna kommer att stöta på något nytt som inte är vettigt. Det är där den globala PostgreSQL-gemenskapen kan komma in för att hjälpa till. Ungefär som steg #0, ju tydligare information som ges till samhället, desto lättare kan de hjälpa till.
5.1. PostgreSQL-e-postlistor
Eftersom PostgreSQL är utvecklat och hanterat av öppen källkod, finns det tusentals människor som pratar genom e-postlistorna för att diskutera otaliga ämnen inklusive funktioner, fel och prestandaproblem. E-postlistorna finns här, där pgsql-admin och pgsql-performance är de viktigaste för att söka hjälp med prestandaproblem.
5.2. IRC
Freenode är värd för flera PostgreSQL-kanaler med utvecklare och administratörer över hela världen, och det är inte svårt att hitta en hjälpsam person för att spåra var problem kan komma ifrån. Mer information finns på PostgreSQL IRC-sidan.