Checkpoints kunnen een grote belemmering zijn voor postgreSQL-installaties met veel schrijven. De eerste stap naar het identificeren van problemen op dit gebied is om te controleren hoe vaak ze voorkomen, wat onlangs een gebruiksvriendelijkere interface heeft gekregen die onlangs aan de database is toegevoegd.
Controlepunten zijn periodieke onderhoudsbewerkingen die de database uitvoert om ervoor te zorgen dat alles wat het in het geheugen heeft opgeslagen, is gesynchroniseerd met de schijf. Het idee is dat als u er eenmaal een hebt voltooid, u zich geen zorgen hoeft te maken over oudere vermeldingen die in het vooruitschrijflogboek van de database worden geplaatst. Dat betekent minder tijd om te herstellen na een crash.
Het probleem met checkpoints is dat ze erg intensief kunnen zijn, want om er een te voltooien, moet elk stukje gewijzigde gegevens in de buffercache van de database naar schijf worden geschreven. Er zijn een aantal functies toegevoegd aan PostgreSQL 8.3 waarmee je de overhead van het checkpoint beter kunt monitoren en verlagen door de activiteit over een langere periode te spreiden. Ik heb een lang artikel geschreven over die veranderingen, Checkpoints and the Background Writer genaamd, waarin wordt besproken wat er is veranderd, maar het is nogal droog om te lezen.
Wat u waarschijnlijk wilt weten, is hoe u controlepunten op uw productiesysteem kunt controleren en hoe u dit kunt zien. als ze te vaak voorkomen. Hoewel de zaken zijn verbeterd, zijn "checkpoint-pieken" waar schijf-I/O echt zwaar wordt, nog steeds mogelijk, zelfs in de huidige PostgreSQL-versies. En het helpt niet dat de standaardconfiguratie is afgestemd op zeer weinig schijfruimte en snel crashherstel in plaats van op prestaties. De parameter checkpoint_segments, die één invoer is voor hoe vaak een checkpoint voorkomt, is standaard 3, wat een checkpoint dwingt na slechts 48 MB schrijfbewerkingen.
Je kunt de frequentie van het checkpoint op twee manieren achterhalen. U kunt log_checkpoints inschakelen en kijken wat er in de logboeken gebeurt. Je kunt ook de weergave pg_stat_bgwriter gebruiken, die een telling geeft van elk van de twee bronnen voor checkpoints (tijd die verstrijkt en schrijfacties) en statistieken over hoeveel werk ze hebben gedaan.
Het grootste probleem om dat gemakkelijker te maken doen is dat het tot voor kort onmogelijk was om de tellers in pg_stat_bgwriter te resetten. Dat betekent dat je een momentopname moet maken met een tijdstempel erop, even moet wachten, nog een momentopname moet maken en vervolgens alle waarden moet aftrekken om bruikbare statistieken uit de gegevens te halen. Dat is vervelend.
Het is zo vervelend dat ik een patch heb geschreven om het gemakkelijker te maken. Met de huidige ontwikkelingsversie van de database kun je nu pg_stat_reset_shared(‘bgwriter’) aanroepen en al deze waarden weer terugzetten naar 0. Dit maakt het mogelijk om een praktijk te volgen die vroeger gebruikelijk was op PostgreSQL. Vóór 8.3 was er een parameter met de naam stats_reset_on_server_start die u kon inschakelen. Die reset alle interne statistieken van de server elke keer dat u hem startte. Dat betekende dat je de handige functie pg_postmaster_start_time() kon aanroepen, vergelijken met de huidige tijd, en altijd een nauwkeurige telling in termen van bewerkingen/seconde van alle beschikbare statistieken op het systeem hebben.
Het is nog steeds niet automatisch, maar nu dat het resetten van deze gedeelde stukken mogelijk is, kunt u zelf doen. De eerste sleutel is om het wissen van statistieken te integreren in de opstartvolgorde van uw server. Een script als dit werkt:
pg_ctl start -l $PGLOG -w
psql -c "select pg_stat_reset();"
psql -c "select pg_stat_reset_shared('bgwriter');"
Let op de "-w" op het start-commando daar - waardoor pg_ctl wacht tot de server klaar is met starten voordat deze terugkeert, wat van vitaal belang is als je er onmiddellijk een statement tegen wilt uitvoeren.
Als je dat hebt gedaan dat, en de starttijd van je server is in wezen hetzelfde als toen de statistieken van de achtergrondschrijver begonnen te verzamelen, kun je nu deze leuke zoekopdracht gebruiken:
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;
En ontvang een eenvoudig rapport van hoe vaak er precies op uw systeem controlepunten plaatsvinden. De uitvoer ziet er als volgt uit:
total_checkpoints | 9
minutes_between_checkpoints | 3.82999310740741
Wat u met deze informatie doet, is staren naar het gemiddelde tijdsinterval en kijken of het te snel lijkt. Normaal gesproken zou je niet vaker dan elke vijf minuten een checkpoint willen hebben, en op een druk systeem moet je het misschien tot tien minuten of langer pushen om de hoop bij te houden. In dit voorbeeld is elke 3,8 minuten waarschijnlijk te snel - dit is een systeem dat checkpoint_segments nodig heeft om hoger te zijn.
Als u deze techniek gebruikt om het checkpoint-interval te meten, weet u of u de parameters checkpoint_segments en checkpoint_timeout in volgorde moet verhogen om dat doel te bereiken. Je kunt de getallen nu handmatig berekenen, en zodra 9.0 is uitgebracht, kun je overwegen om het volledig automatisch te maken, zolang je het niet erg vindt dat je statistieken verdwijnen telkens wanneer de server opnieuw wordt opgestart.
Er zijn nog een aantal andere interessante manieren om de gegevens te analyseren die de achtergrondschrijver voor u levert in pg_stat_bgwriter, maar ik ga vandaag niet al mijn trucs verklappen.