Kontrollpunkter kan vara ett stort hinder för skrivtunga PostgreSQL-installationer. Det första steget mot att identifiera problem inom detta område är att övervaka hur ofta de inträffar, vilket nyligen har lagts till ett mer lättanvänt gränssnitt i databasen.
Kontrollpunkter är periodiska underhållsoperationer som databasen utför för att säkerställa att allt som den har cachelagrat i minnet har synkroniserats med disken. Tanken är att när du är klar med en, kan du inte behöva oroa dig för äldre poster som placeras i databasens skrivförskottslogg. Det betyder mindre tid att återhämta sig efter en krasch.
Problemet med kontrollpunkter är att de kan vara mycket intensiva, eftersom för att slutföra en sådan krävs att man skriver ut varenda bit av ändrad data i databasens buffertcache till disk. Det har lagts till ett antal funktioner i PostgreSQL 8.3 som gör att du bättre kan övervaka kontrollpunkten över huvudet och sänka den genom att sprida aktiviteten över en längre tidsperiod. Jag skrev en lång artikel om de förändringarna som heter Checkpoints and the Background Writer som går igenom vad som förändrades, men det är ganska torr läsning.
Vad du förmodligen vill veta är hur man övervakar kontrollpunkter i ditt produktionssystem och hur man berättar om de händer för ofta. Även om saker och ting har förbättrats, är "checkpoint spikes" där disk I/O blir riktigt tung fortfarande möjliga även i nuvarande PostgreSQL-versioner. Och det hjälper inte att standardkonfigurationen är inställd för mycket lite diskutrymme och snabb kraschåterställning snarare än prestanda. Parametern checkpoint_segments som är en indata om hur ofta en kontrollpunkt inträffar är standard till 3, vilket tvingar fram en kontrollpunkt efter bara 48 MB skrivningar.
Du kan ta reda på kontrollpunktsfrekvensen på två sätt. Du kan slå på log_checkpoints och se vad som händer i loggarna. Du kan också använda vyn pg_stat_bgwriter, som ger en räkning av var och en av de två källorna för kontrollpunkter (tid som går och skrivningar som inträffar) samt statistik om hur mycket arbete de gjorde.
Det största problemet med att göra det lättare att gör är att tills nyligen har det varit omöjligt att återställa räknarna inuti pg_stat_bgwriter. Det betyder att du måste ta en ögonblicksbild med en tidsstämpel på, vänta ett tag, ta en till ögonblicksbild och sedan subtrahera alla värden för att härleda all användbar statistik från data. Det är jobbigt.
Det är nog av smärta att jag skrev ett plåster för att göra det lättare. Med den aktuella utvecklingsversionen av databasen kan du nu anropa pg_stat_reset_shared(‘bgwriter’) och återställa alla dessa värden till 0 igen. Detta gör det möjligt att följa en praxis som brukade vara vanlig på PostgreSQL. Före 8.3 fanns det en parameter med namnet stats_reset_on_server_start som du kunde aktivera. Det återställde all serverns interna statistik varje gång du startade den. Det innebar att du kunde anropa den praktiska pg_postmaster_start_time()-funktionen, jämföra med den aktuella tiden och alltid ha en korrekt räkning i termer av operationer/sekund av all statistik tillgänglig på systemet.
Det är fortfarande inte automatiskt, men nu att det är möjligt att återställa dessa delade delar kan du göra det själv. Den första nyckeln är att integrera statistikrensning i din serverstartsekvens. Ett skript som detta kommer att fungera:
pg_ctl start -l $PGLOG -w
psql -c "select pg_stat_reset();"
psql -c "select pg_stat_reset_shared('bgwriter');"
Notera "-w" på startkommandot där – som gör att pg_ctl väntar tills servern är klar med start innan den återvänder, vilket är viktigt om du omedelbart vill köra en sats mot den.
Om du har gjort det. det, och din serverstarttid är i stort sett densamma som när bakgrundsförfattarstatistiken började samla in, kan du nu använda den här roliga frågan:
SELECT
total_checkpoints,
seconds_since_start / total_checkpoints / 60 AS minutes_between_checkpoints
FROM
(SELECT
EXTRACT(EPOCH FROM (now() - pg_postmaster_start_time())) AS seconds_since_start,
(checkpoints_timed+checkpoints_req) AS total_checkpoints
FROM pg_stat_bgwriter
) AS sub;
Och få en enkel rapport om exakt hur ofta kontrollpunkter sker på ditt system. Utdatan ser ut så här:
total_checkpoints | 9
minutes_between_checkpoints | 3.82999310740741
Vad du gör med denna information är att stirra på det genomsnittliga tidsintervallet och se om det verkar för snabbt. Normalt vill du att en kontrollpunkt inte ska hända mer än var femte minut, och på ett upptaget system kan du behöva pressa den till tio minuter eller mer för att ha ett hopp om att hänga med. Med det här exemplet är förmodligen var 3,8:e minut för snabbt – det här är ett system som kräver att checkpoint_segments är högre.
Om du använder den här tekniken för att mäta checkpointintervallet kan du veta om du behöver öka parametrarna checkpoint_segments och checkpoint_timeout i ordning för att uppnå det målet. Du kan beräkna siffrorna manuellt just nu, och när 9.0 väl har skickats är det något du kan överväga att göra helt automatiskt – så länge du inte har något emot att din statistik försvinner varje gång servern startar om.
Det finns några andra intressanta sätt att analysera data som bakgrundsskribenten tillhandahåller dig i pg_stat_bgwriter, men jag tänker inte ge bort alla mina knep idag.