En av de intressanta funktionerna i PostgreSQL sedan version 9.4 är möjligheten att kontrollera borttagning av WAL-filer med hjälp av replikeringsplatser. Den mörka sidan är att replikeringsplatser kan få diskar att fyllas upp med gammal WAL, vilket dödar huvudproduktionsservern. I den här artikeln förklarar jag PostgreSQL-replikeringsplatser och hur en ny funktion i PostgreSQL 13 hjälper till att förhindra detta problem.
WAL-produktion
Som ni vet produceras WAL för databasändringar i en primär server:infogning, uppdatering, et cetera . En mer aktiv databas kommer att producera mer WAL — på en mycket aktiv server kan det produceras många gigabyte WAL varje minut. WAL skrivs till filer med namn i en ökande numerisk sekvens, och filerna har alltid samma storlek (16 MB är standard och typiskt). När data i en fil inte längre behövs kan den filen återvinnas , vilket innebär att döpa om den till en högre numrerad position i sekvensen så att den kan fyllas med ny data senare.
(Det finns speciella situationer som en ökning av aktiviteten som leder till skapandet av ytterligare filer; när ökningen senare dämpas tas de extra filerna bort istället för att återvinnas.)
Eftersom all databasskrivaktivitet producerar WAL är det avgörande att diskutrymme är tillgängligt. När disken som lagrar WAL är full kommer servern inte att kunna bearbeta nya transaktioner och kan fastna, eller ännu värre:den kan ramla omkull helt. Så detta är en situation som ska undvikas med alla möjliga medel.
Replikeringsplatser
Replikering i PostgreSQL fungerar genom att bearbeta WAL-filer. För att detta ska fungera måste alla WAL-filer vara tillfälligt tillgängliga tills de bearbetas. Därför behövs en mekanism för att tala om för den huvudsakliga WAL-ledningen att inte återvinna eller ta bort filer.
Ange replikeringsplatser. Slots är en mekanism som indikerar att detta säkerhetskopiering som vi tar kräver det WAL-fil, och kan du inte ta bort den ännu; eller denna repliken har fortfarande inte bearbetat det WAL-fil, så kan den lämnas ifred en liten stund.
I sig själva upptar replikeringsplatser väldigt lite diskutrymme. De lagrar bara en liten bit av metadata, inklusive en pekare till en position i WAL. Men WAL-data som den skyddar är en annan sak:på en mycket aktiv server kan den mätas i gigabyte eller ännu värre.
WAL-förbrukning
Att mata data till en fysisk replik innebär att kopiera WAL-data från dess primära server. På liknande sätt behöver en logisk replik läsa WAL-data (och överföra en tolkad version till repliken). WAL-positionen som läses är vad luckan håller reda på. När repliken har säkrat WAL-data på något sätt, kan luckan flyttas fram; detta talar om för WAL-ledningen i den primära att WAL-filen då är tillgänglig för borttagning. Detta sker kontinuerligt när repliken är aktiv, så att WAL i den primära servern kommer att använda samma mängd diskutrymme eller kanske bara lite mer. Även dubbelt så mycket eller tio gånger så mycket kan vara acceptabelt, beroende på förhållandena.
Problemet är att om en replik dör helt och inte återhämtar sig under en lång tid; eller så förstörs repliken och DBA glömmer att ta bort replikeringsplatsen; eller platsen är en bortglömd rest av något experiment; eller till och med repliken matas över en långsam nätverkslänk, då kommer den reserverade WAL att växa utan gränser. Och det blir en tickande bomb.
Begränsning av platsstorlek
För att bekämpa detta problem hade Kyotaro Horiguchi arbetat sedan februari 2017 i en PostgreSQL-patch för att begränsa storleken på WAL reserverad av en slot. Efter en mycket lång granskning och omarbetningsprocess integrerade jag den för PostgreSQL 13, vilket förbättrade hanteringen av PostgreSQL-farmar med hög tillgänglighet.
Huvudprincipen är att det är bättre att döda en replik (genom att på något sätt göra dess slot ogiltig, mer om det nedan) än att döda den primära servern som matar den repliken och ta ner all produktion med den.
Sättet det fungerar på är ganska enkelt:ställ in max_slot_wal_keep_size
(dokumentation) i postgresql.conf till den maximala mängden diskutrymme för WAL som replikeringsplatser får reservera. Om en plats når den punkten och en kontrollpunkt inträffar kommer den luckan att markeras ogiltig och vissa WAL-filer kan raderas. Om spelautomaten användes aktivt av en walsender process, kommer den processen att signaleras så att den avslutas. Om walsender startar igen kommer den att upptäcka att nödvändiga WAL-filer inte finns där längre. Repliken som använder den platsen måste klonas om.
Om max_slot_wal_keep_size
är noll, vilket är standardvärdet, då finns det ingen gräns. Jag rekommenderar inte detta, eftersom det leder till fel när platser fyller disken.
Övervaka spelautomatens hälsa
Vissa övervakningsfunktioner ingår också. Två kolumner i pg_replication_slots är relevanta. Den mest kritiska är wal_status
. Om den kolumnen är reserved
, då pekar luckan på data inom max_wal_size
; om den är extended
sedan överskred den max_wal_size
, men är fortfarande skyddad av antingen wal_keep_size
eller max_slot_wal_keep_size
(inklusive när max_slot_wal_keep_size
är noll). Båda tillstånden är bra och normala. Men när en plats kommer över gränsen blir den först unreserved
, vilket innebär att det är i överhängande fara, men kan fortfarande återhämta sig om det är tillräckligt snabbt. Slutligen blir statusen lost
när WAL-filer har tagits bort och ingen återställning är möjlig.
Den andra kolumnen är safe_wal_size
:den visar antalet byte av WAL som kan skrivas innan denna plats riskerar att ta bort WAL-filer. Vi föreslår att du håller ett öga på den här kolumnen i ditt övervakningssystem och larmar när det blir lågt. Noll eller negativ betyder att din replik kommer att vara död så snart en kontrollpunkt inträffar:
SELECT slot_name, active, wal_status, safe_wal_size FROM pg_catalog.pg_replication_slots;
Vi tror att denna nya funktion gör underhållet av repliker enklare och mer robust; förhoppningsvis kommer vi inte att se några fler katastrofer med produktionen nere på grund av dessa problem.
(En notering:safe_wal_size
introducerades i 13beta3, så se till att läsa uppdaterad dokumentation, annars ser du min_safe_lsn
istället. Ignorera det.)
Tack
Speciellt tack till Kyotaro Horiguchi för att han arbetat med att lösa detta problem. Flera recensenter fördjupade sig i detta, bland vilka jag skulle vilja tacka särskilt Masahiko Sawada, Fujii Masao, Jehan-Guillaume de Rorthais och Amit Kapila (utan särskild ordning).