Vanliga misstag i applikationer som leder till bloat i PostgreSQL. Andrej Salnikov

Jag föreslÄr att ni bekantar er med avrapporteringen frÄn början av 2016 av Andrej Salnikov "Typiska fel i applikationer som leder till bloat i PostgreSQL"

I den hÀr rapporten kommer jag att gÄ igenom de vanligaste felen i applikationer som uppstÄr under design- och kodningsfasen av applikationen. Jag kommer endast att ta upp de fel som leder till bloat i PostgreSQL. Vanligtvis Àr detta början pÄ slutet för systemets prestanda som helhet, Àven om det frÄn början inte fanns nÄgra tecken pÄ detta.

Vanliga misstag i applikationer som leder till bloat i PostgreSQL. Andrej Salnikov

Jag hÀlsar er alla vÀlkomna! Denna förelÀsning Àr inte lika teknisk som den föregÄende frÄn min kollega. Den hÀr förelÀsningen riktar sig frÀmst till utvecklare av backend-system, eftersom vi har ett ganska stort antal kunder. Och alla gör samma misstag. Det Àr om dessa jag kommer att berÀtta. Jag kommer att förklara vilka katastrofala och negativa konsekvenser dessa fel kan leda till.

Vanliga misstag i applikationer som leder till bloat i PostgreSQL. Andrej Salnikov

Varför uppstÄr felen? De uppstÄr av tvÄ anledningar: antingen genom tur, att det kanske fungerar, eller av okunskap om vissa mekanismer som hÀnder pÄ nivÄn mellan databasen och applikationen, samt i sjÀlva databasen.

Jag kommer att ge er tre exempel med hemska bilder av hur allt blev dÄligt. Jag kommer kort att beskriva de mekanismer som förekommer dÀr. Och hur man kan hantera dem nÀr de intrÀffar, samt vilka förebyggande metoder som kan anvÀndas för att undvika fel. Jag kommer att berÀtta om hjÀlpprogram och ge anvÀndbara lÀnkar.

Vanliga misstag i applikationer som leder till bloat i PostgreSQL. Andrej Salnikov

Jag anvÀnde en testdatabas dÀr jag hade tvÄ tabeller. En tabell för kundkonton och den andra för transaktioner pÄ dessa konton. Med viss periodicitet uppdaterar vi saldona pÄ dessa konton.

Vanliga misstag i applikationer som leder till bloat i PostgreSQL. Andrej Salnikov

Ursprungliga data för tabellen: den Ă€r ganska liten, 2 MB. Svarstiden för databasen och specifikt för tabellen Ă€r ocksĂ„ mycket bra. Och en ganska bra belastning – 2 000 operationer per sekund pĂ„ tabellen.

Vanliga misstag i applikationer som leder till bloat i PostgreSQL. Andrej Salnikov

Och genom denna förelÀsning kommer jag att visa er grafer sÄ att det tydligt ska framgÄ vad som hÀnder. Det kommer alltid att finnas 2 bilder med grafer. Den första bilden visar vad som hÀnder i allmÀnhet pÄ servern.

Och i denna situation ser vi att vi verkligen har en tabell av liten storlek. Indexet Àr litet, pÄ 2 MB. Detta Àr den första grafen till vÀnster.

Den genomsnittliga svarstiden för servern Àr ocksÄ stabil och lÄg. Detta Àr den övre grafen till höger.

Den nedersta vÀnstra grafen visar de lÀngsta transaktionerna. Vi ser att transaktionerna genomförs snabbt. Och autovakuum fungerar Ànnu inte hÀr, eftersom det var ett starttest. Framöver kommer det att fungera och vara till nytta för oss.

Vanliga misstag i applikationer som leder till bloat i PostgreSQL. Andrej Salnikov

Den andra bilden kommer alltid att handla om den testade tabellen. I den hÀr situationen uppdaterar vi kontinuerligt saldot pÄ kundens konton. Och vi ser att den genomsnittliga svarstiden för uppdateringsoperationen Àr ganska bra, mindre Àn en millisekund. Vi ser ocksÄ att CPU-resurserna (det Àr den övre högra grafen) förbrukas jÀmnt och i ganska smÄ mÀngder.

Den nedre högra grafen visar hur mycket operativ och diskminne vi gĂ„r igenom i sökandet efter vĂ„r nödvĂ€ndiga rad innan vi uppdaterar den. Och antalet operationer pĂ„ tabellen – 2000 per sekund, precis som jag nĂ€mnde tidigare.

Vanliga misstag i applikationer som leder till bloat i PostgreSQL. Andrej Salnikov

Och nu hÀnder det en tragedi. Av nÄgon anledning uppstÄr en lÄng glömd transaktion. Orsakerna Àr vanligtvis banala:

  • En av de vanligaste situationerna Ă€r att vi i applikationskoden börjar anropa en extern tjĂ€nst. Och den tjĂ€nsten svarar inte oss. Det vill sĂ€ga, vi öppnade en transaktion, gjorde en Ă€ndring i databasen och gick för att lĂ€sa e-post i applikationen eller till en annan tjĂ€nst i vĂ„r infrastruktur, och av nĂ„gon anledning svarar den inte oss. Och vĂ„r session hĂ€nger i ett tillstĂ„nd – oklart nĂ€r det ska lösas.
  • Den andra situationen Ă€r nĂ€r det i koden av nĂ„gon anledning uppstod ett undantag. Och vi i undantaget inte hanterade stĂ€ngningen av transaktionen. Och vi har fĂ„tt en hĂ€ngande session med en öppen transaktion.
  • Och den sista – det Ă€r ocksĂ„ ett ganska vanligt fall. Det handlar om undermĂ„lig kod. Vissa ramverk öppnar en transaktion. Den hĂ€nger, och du kan vara ovetande om att den hĂ€nger i applikationen.

Vad leder sÄdana saker till?

Till att vÄra tabeller och index börjar svÀlla kraftigt. Det hÀr Àr just den effekt som kallas bloat. För databasen kommer det att innebÀra att vi fÄr en dramatisk ökning i databasens svarstid, ökad belastning pÄ databasservern. Och som ett resultat kommer applikationen att lida. För om du i koden tog 10 millisekunder för en förfrÄgan till databasen, 10 millisekunder för din logik, sÄ fungerade din funktion pÄ 20 millisekunder. Men nu kommer situationen att bli helt sorglig.

LÄt oss se vad som hÀnder. Den vÀnstra nedre grafen visar att vi har en lÄngvarig transaktion. Och om vi tittar pÄ den vÀnstra övre grafen ser vi att storleken pÄ tabellen, som var tvÄ megabyte, plötsligt har ökat till 300 megabyte. Samtidigt har mÀngden data i tabellen inte förÀndrats, dvs. det finns en stor mÀngd skrÀp.

Vanliga misstag i applikationer som leder till bloat i PostgreSQL. Andrej Salnikov

Den övergripande situationen för medelservartid har ocksÄ förÀndrats flera gÄnger. Det vill sÀga alla förfrÄgningar till servern har börjat sjunka kraftigt. Samtidigt har interna Postgres-processer i form av autovakuum startat, som försöker göra nÄgot och förbrukar resurser.

Vanliga misstag i applikationer som leder till bloat i PostgreSQL. Andrej Salnikov

Vad hÀnder med vÄr tabell? Samma sak. Medel svarstid för tabellen har ökat flera gÄnger. NÀr vi ser pÄ de anvÀnda resurserna, ser vi att belastningen pÄ processorn har ökat kraftigt. Det Àr den övre högra grafen. Den har ökat eftersom processorn mÄste gÄ igenom massor av vÀrdelösa rader för att hitta en enda som behövs. Det Àr den nedre högra grafen. Som ett resultat har antalet anrop per sekund börjat sjunka kraftigt eftersom databasen inte hinner bearbeta samma mÀngd förfrÄgningar.

Vanliga misstag i applikationer som leder till bloat i PostgreSQL. Andrej Salnikov

Vi mÄste komma tillbaka till livet. Vi gÄr in pÄ internet och fÄr reda pÄ att lÄngvariga transaktioner orsakar problem. Vi hittar och dödar denna transaktion. Och nu fungerar allt som det ska. Allt fungerar bra.

Vi lugnar ner oss, men efter ett tag börjar vi mÀrka att applikationen inte fungerar som den gjorde före incidenten. FörfrÄgningar bearbetas fortfarande lÄngsammare, och faktiskt betydligt lÄngsammare. I mitt fall Àr det en och en halv till tvÄ gÄnger lÄngsammare. Belastningen pÄ servern Àr ocksÄ högre Àn den var före incidenten.

Vanliga misstag i applikationer som leder till bloat i PostgreSQL. Andrej Salnikov

Och frÄgan Àr: "Vad hÀnder med databasen vid det tillfÀllet?". Med databasen sker följande: I grafen för transaktioner ser ni att den har stannat och det finns verkligen inga lÄngvariga transaktioner dÀr. Men storleken pÄ tabellen har under incidenten ökat katastrofalt. Och har inte minskat sedan dess. Medeltiden för databasen har stabiliserats. Svaren verkar komma fram i en acceptabel hastighet för oss. Autovakuum har blivit mer aktivt och har börjat göra nÄgot med tabellen, för det behöver bearbeta en större mÀngd data.

Vanliga misstag i applikationer som leder till bloat i PostgreSQL. Andrej Salnikov

Specifikt för den testade fakturatabellen, dÀr vi Àndrar saldon: svarstiden pÄ förfrÄgan verkar ha ÄtergÄtt till det normala. Men i sjÀlva verket Àr den en och en halv gÄng högre.

Och nÀr det gÀller CPU-belastningen ser vi att den inte har ÄtergÄtt till rÀtt nivÄ innan kraschen. Orsaken döljer sig precis i den nedre högra grafen. Det Àr tydligt att nÄgot slags minnesöverskott sker dÀr. D.v.s. för att hitta den nödvÀndiga raden förbrukar vi serverresurser i databasen nÀr vi gÄr igenom onödiga data. Antalet transaktioner per sekund har stabiliserats.

Överlag Ă€r det bra, men situationen Ă€r vĂ€rre Ă€n vad den var. En tydlig nedgĂ„ng i databasen som en följd av vĂ„r applikation som arbetar med denna databas.

Vanliga misstag i applikationer som leder till bloat i PostgreSQL. Andrej Salnikov

Och för att förstÄ vad som hÀnder dÀr, om ni inte var pÄ den föregÄende presentationen, sÄ kommer lite teori nu. Teorin om den interna processen. Vad Àr autovakuum och vad gör det?

Kort sagt för att förstÄ. Vid nÄgon tidpunkt har vi en tabell. I tabellen finns rader. Dessa rader kan vara aktiva, livliga, viktiga för oss nu. PÄ bilden Àr de markerade i grönt. Och det finns döda rader, som redan har anvÀnts, har uppdaterats, nya poster har tillkommit. De Àr markerade eftersom de inte lÀngre intresserar databasen. Men de ligger kvar i tabellen pÄ grund av PostgreSQL:s egenskaper.

Vad behövs autovakuum för? Autovakuum kommer vid nÄgot tillfÀlle, kontaktar databasen och frÄgar: "Ge mig vÀnligen id för den Àldsta transaktionen som för nÀrvarande Àr öppen i databasen." Databasen returnerar detta id. Och autovakuum, baserat pÄ detta, gÄr igenom raderna i tabellen. Om det ser att vissa rader har förÀndrats av betydligt Àldre transaktioner, har det rÀtt att markera dem som rader som vi kan ÄteranvÀnda i framtiden genom att skriva nya data dÀr. Detta Àr en bakgrundsprocess.

Under tiden fortsÀtter vi att arbeta med databasen, fortsÀtter att göra olika Àndringar i tabellen. Och pÄ dessa rader, som vi kan ÄteranvÀnda, skriver vi ny data. PÄ sÄ sÀtt fÄr vi ett kretslopp, d.v.s. hela tiden uppstÄr det döda gamla rader, istÀllet skriver vi nya rader som vi behöver. Och detta Àr ett normalt tillstÄnd för att arbeta med PostgreSQL.

Vanliga misstag i applikationer som leder till bloat i PostgreSQL. Andrej Salnikov

Vad hÀnde under kraschen? Hur gick processen till dÀr?

Vi hade en tabell i nÄgot tillstÄnd, vissa rader levande och andra döda. Autofragmentering kom. Den frÄgade databasen om vilken som var vÄr Àldsta transaktion och vilket id den hade. Den fick det id som kan vara flera timmar gammalt eller bara tio minuter. Det beror pÄ hur hög belastning ni har i databasen. Sedan började den leta efter rader som den kan mÀrka som ÄteranvÀndbara. Men den hittade inga sÄdana rader i vÄr tabell.

Men under tiden fortsÀtter vi att arbeta med tabellen. Vi gör nÄgot i den, uppdaterar, Àndrar data. Vad har databasen att göra under tiden? Den har inget annat att göra Àn att skriva nya rader i slutet av den befintliga tabellen. PÄ sÄ sÀtt börjar storleken pÄ tabellen att öka.

För vÄrt arbete behöver vi egentligen gröna rader. Men under ett sÄdant problem fÄr vi att procentandelen gröna rader Àr extremt lÄg i hela tabellen.

NÀr vi gör en förfrÄgan mÄste databasen gÄ igenom alla rader: bÄde röda och gröna, för att hitta den nödvÀndiga raden. Effekten av att tabellen svullnar upp med onödiga data kallas 'bloat', som ocksÄ slukar vÄrt diskutrymme. Kommer ni ihÄg, det var 2 MB, nu Àr det 300 MB? Och nu, byt megabyte mot gigabyte sÄ kommer ni snabbt att förlora alla era disresurser.

Vanliga misstag i applikationer som leder till bloat i PostgreSQL. Andrej Salnikov

Vilka konsekvenser kan det fÄ för oss?

  • I mitt exempel har tabellen och indexet vuxit med 150 gĂ„nger. Hos vissa av vĂ„ra kunder har det intrĂ€ffat mer fatala fall nĂ€r det helt enkelt börjar ta slut pĂ„ diskutrymme.
  • Storleken pĂ„ tabellerna minskar aldrig av sig sjĂ€lv. Autofragmentering kan i vissa fall klippa av svansen pĂ„ tabellen om det bara finns döda rader. Men eftersom en konstant rotation sker kan en grön rad hĂ€nga kvar i slutet och inte uppdateras, medan alla andra kommer att skrivas nĂ„gonstans i början av tabellen. Men det Ă€r ett sĂ„ osannolikt scenario att ni inte bör hoppas pĂ„ att er tabell kommer att minska i storlek.
  • Databasen mĂ„ste gĂ„ igenom hela högen av onödiga rader. Och vi slösar med disresurser, slösar med CPU-resurser och elektricitet.
  • Och detta pĂ„verkar direkt vĂ„r applikation, för om vi i början anvĂ€nde 10 millisekunder för en begĂ€ran, 10 millisekunder för vĂ„r kod, sĂ„ började vi under kraschen att anvĂ€nda en sekund för begĂ€ran och 10 millisekunder för koden, det vill sĂ€ga applikationens prestanda sjönk ordentligt. NĂ€r kraschen löstes började vi anvĂ€nda 20 millisekunder för begĂ€ran och 10 millisekunder för koden. Det betyder att vi fortfarande har en prestandaförlust pĂ„ en och en halv gĂ„ng. Och allt detta pĂ„ grund av en transaktion som fryst, möjligtvis pĂ„ vĂ„rt fel.
  • Och frĂ„gan Ă€r: "Hur fĂ„r vi tillbaka allt?" SĂ„ att allt fungerar bra och begĂ€rningarna gĂ„r lika snabbt som före kraschen.

Vanliga misstag i applikationer som leder till bloat i PostgreSQL. Andrej Salnikov

För detta finns en viss arbetscykel som genomförs.

Först mÄste vi hitta de problematiska tabellerna som har svullnat. Vi förstÄr att för vissa tabeller gÄr inspelningen mer aktivt, för andra mindre aktivt. Och för detta anvÀnds tillÀgget pgstattuple. Genom att installera detta tillÀgg kan du skriva frÄgor som hjÀlper dig att hitta tabeller som har svullnat kraftigt.

Efter att du har funnit dessa tabeller mĂ„ste de komprimeras. För detta finns redan verktyg. I vĂ„rt företag anvĂ€nder vi tre verktyg. Den första Ă€r den inbyggda VACUUM FULL. Den Ă€r grym, strikt och obarmhĂ€rtig, men ibland Ă€r den mycket anvĂ€ndbar. Pg_repack och pgcompacttable – detta Ă€r externa verktyg för komprimering av tabeller. Och de Ă€r mer skonsamma mot databasen.

De anvÀnds beroende pÄ vad som Àr mer bekvÀmt för dig. Men jag kommer att berÀtta mer om detta i slutet. Det viktiga Àr att det finns tre verktyg. Det finns att vÀlja pÄ.

Efter att vi har gjort alla korrigeringar och sÀkerstÀllt att allt fungerar bra, mÄste vi veta hur vi hindrar denna situation i framtiden:

  • Det Ă€r ganska enkelt att förebygga. Man behöver hĂ„lla koll pĂ„ lĂ€ngden pĂ„ sessionerna pĂ„ mĂ€sterservern. SĂ€rskilt farliga sessioner i tillstĂ„ndet idle in transaction. Det Ă€r de som precis har öppnat en transaktion, gjort nĂ„got och sedan gĂ„tt dĂ€rifrĂ„n eller bara fryst, förlorat sig i koden.
  • Och för er, som utvecklare, Ă€r det viktigt att testa koden vid uppkomsten av sĂ„dana situationer. Det Ă€r inte svĂ„rt att göra. Det kommer att vara en nyttig kontroll. Ni undviker mĂ„nga "barnsjukdomar" relaterade till lĂ„nga transaktioner.

Vanliga misstag i applikationer som leder till bloat i PostgreSQL. Andrej Salnikov

I wanted to show you on these graphs how the table and database behavior changed after I performed a VACUUM FULL on the table. This is not in production.

The table size immediately returned to a normal working state of a few megabytes. This did not significantly affect the average response time on the server.

Vanliga misstag i applikationer som leder till bloat i PostgreSQL. Andrej Salnikov

However, specifically for our test table, where we updated the account balances, we see that the average response time for the data update query has decreased to pre-incident levels. The CPU resources consumed for executing this query have also fallen to pre-incident levels. The bottom right graph shows that we are now finding exactly the row we need immediately, without sifting through a bunch of dead rows that existed before the table compression. The average query response time has remained approximately at the same level, but here I might have a deviation due to my hardware.

Vanliga misstag i applikationer som leder till bloat i PostgreSQL. Andrej Salnikov

This concludes the first story. It is the most common one and happens to everyone, regardless of the client's experience or how qualified the programmers are. Sooner or later, this occurs.

The second story, where we distribute the load and optimize server resources.

Vanliga misstag i applikationer som leder till bloat i PostgreSQL. Andrej Salnikov

  • We have grown and become quite serious. We understand that we have a replica and it would be good to balance the load: write to the Master and read from the replica. This situation usually arises when we want to prepare some reports or ETL. The business is very pleased with this. It greatly desires various reports with plenty of complex analysis.
  • The reports take hours, as complex analytics can't be computed in milliseconds. We, as diligent folks, write the code. We perform inserts in the application, writing to the Master and executing reports on the replica.
  • We distribute the load.
  • Everything works excellently. We are doing great.

Vanliga misstag i applikationer som leder till bloat i PostgreSQL. Andrej Salnikov

And how does this situation look? Specifically on these graphs, I also added the duration of transactions from the replica. All other graphs pertain only to the Master server.

Rapporttabellen har vuxit vid det hÀr laget. Vi ser att den genomsnittliga svarstiden för servern Àr stabil. Vi noterar att det finns en lÄngvarig transaktion pÄ repliken som pÄgÄr i tvÄ timmar. Vi ser att autovakuumen arbetar lugnt och bearbetar döda rader. Allt Àr bra.

Vanliga misstag i applikationer som leder till bloat i PostgreSQL. Andrej Salnikov

Specifikt för den aktuella tabellen fortsÀtter vi att uppdatera saldon. Vi har ocksÄ stabil svarstid för förfrÄgan och stabil resursanvÀndning. Allt Àr bra.

Vanliga misstag i applikationer som leder till bloat i PostgreSQL. Andrej Salnikov

Allt Àr bra tills dessa rapporter börjar skjutas upp pÄ grund av konflikter med replikationen. De skjuts upp med konstant periodicitet.

Vi gÄr ut pÄ nÀtet och börjar lÀsa varför detta hÀnder. Och vi hittar en lösning.

Den första lösningen Àr att öka replikationsfördröjningen. Vi vet att vÄr rapport tar tre timmar. Vi sÀtter replikationsfördröjningen till tre timmar. Vi startar allt, men vi har fortfarande problem med att rapporterna ibland skjuts upp.

Vi vill att allt ska vara perfekt. Vi fortsĂ€tter leta. Och vi hittar en fantastisk instĂ€llning pĂ„ nĂ€tet – hot_standby_feedback. Vi aktiverar det. Hot_standby_feedback lĂ„ter oss hĂ„lla autovakuumets arbete pĂ„ Master. PĂ„ sĂ„ sĂ€tt slipper vi helt konflikter vid replikation. Allt fungerar bra med rapporterna.

Vanliga misstag i applikationer som leder till bloat i PostgreSQL. Andrej Salnikov

Och vad hÀnder med Master-servern under tiden? Med Master-servern har vi total katastrof. Just nu observerar vi graferna nÀr jag aktiverade bÄda dessa instÀllningar. Vi ser att sessionen pÄ repliken pÄ nÄgot sÀtt börjar pÄverka situationen pÄ Master-servern. Det pÄverkar verkligen, eftersom den har pausat autovakuumet som rensar döda rader. Storleken pÄ tabellen har Äterigen skjutit i höjden. Den genomsnittliga frÄgetiden för hela databasen har ocksÄ skjutit i höjden. Autovakuumen har blivit nÄgot anstrÀngda.

Vanliga misstag i applikationer som leder till bloat i PostgreSQL. Andrej Salnikov

Specifikt för vÄr tabell ser vi att datan ocksÄ har skjutit i höjden. ResursanvÀndningen för CPU har ocksÄ ökat kraftigt. Vi gÄr Äterigen igenom ett stort antal döda, meningslösa rader. Och svarstiden för denna tabell och antalet transaktioner har minskat.

Vanliga misstag i applikationer som leder till bloat i PostgreSQL. Andrej Salnikov

Hur skulle det se ut om vi inte visste vad jag pratat om tidigare?

  • Vi börjar leta efter problem. Om vi har stött pĂ„ problem i första delen vet vi att det kan bero pĂ„ en lĂ„ng transaktion och vi kollar pĂ„ Master. Problemet finns pĂ„ vĂ„r Master. Den har problem. Den blir varm och dess Load Average nĂ€rmar sig hundra.
  • FörfrĂ„gningar dĂ€r hĂ€nger sig, men vi ser inga lĂ„ngvariga transaktioner. Och vi förstĂ„r inte vad som Ă€r fel. Vi förstĂ„r inte var vi ska leta.
  • Vi kontrollerar serverhĂ„rdvaran. Kanske har vĂ„r raid kraschat. Kanske har ett minnesmodul brunnit. Vad som helst kan hĂ€nda. Men nej, servrarna Ă€r nya, allt fungerar utmĂ€rkt.
  • Alla springer omkring: administratörer, utvecklare och direktören. Inget hjĂ€lper.
  • Och plötsligt börjar allt oannonserat att Ă„terstĂ€llas av sig sjĂ€lvt.

Vanliga misstag i applikationer som leder till bloat i PostgreSQL. Andrej Salnikov

PÄ replikan har en förfrÄgan under tiden utförts och skickats ivÀg. Vi fick en rapport. Företaget Àr fortfarande nöjt. Som vi ser har vÄr tabell vÀxt igen och visar inga tecken pÄ minskning. PÄ grafen med sessioner har jag lÀmnat ett stycke av denna lÄnga transaktion frÄn replikan sÄ att ni kan bedöma hur lÄng tid det tar innan situationen stabiliseras.

Sessionen har avslutats. Och först efter en tid kommer servern mer eller mindre i ordning. Och den genomsnittliga svarstiden pÄ förfrÄgningar pÄ Master-servern normaliseras. För Àntligen har autovacuum fÄtt möjlighet att rensa upp, markera dessa döda rader. Och ju snabbt det arbetar, desto snabbare kommer vi i ordning.

Vanliga misstag i applikationer som leder till bloat i PostgreSQL. Andrej Salnikov

PÄ den testade tabellen, dÀr vi uppdaterar saldon pÄ konton, ser vi ett exakt samma mönster. Den genomsnittliga tiden för kontouppdatering normaliseras ocksÄ gradvis. CPU-anvÀndningen minskar ocksÄ. Och antalet transaktioner per sekund ÄtergÄr till det normala. Men inte till det normala som vi hade innan avbrottet.

Vanliga misstag i applikationer som leder till bloat i PostgreSQL. Andrej Salnikov

I vilket fall fÄr vi en prestationsförlust precis som i första fallet, en och en halv till tvÄ gÄnger, ibland Ànnu mer.

Vi verkar ha gjort allt rÀtt. Fördelat lasten. Utrustningen stÄr inte still. Vi har förnuftigt delat upp förfrÄgningarna, men ÀndÄ blev allt dÄligt.

  • Ska vi inte aktivera hot_standby_feedback? Ja, det rekommenderas vanligtvis inte att aktivera det utan starka skĂ€l. Eftersom den hĂ€r instĂ€llningen direkt pĂ„verkar Master-servern och pausar autovakuumet dĂ€r. Om du aktiverar det pĂ„ en replik och glömmer bort det kan du skada Master och fĂ„ stora problem med applikationen.
  • Ska vi öka max_standby_streaming_delay? Ja, det Ă€r faktiskt sĂ„. Om du har en tre timmar lĂ„ng rapport och inte vill att den ska krascha pĂ„ grund av replikationskonflikter, sĂ„ öka bara fördröjningen. LĂ„nga rapporter krĂ€ver aldrig data som just nu kommit in i databasen. Om den Ă€r tre timmar lĂ„ng, kör du den för nĂ„gon gammal dataperiod. Tre timmars fördröjning eller sex timmars fördröjning spelar ingen roll, men dĂ„ fĂ„r du stabilt dina rapporter och slipper krascher.
  • SjĂ€lvklart mĂ„ste vi övervaka lĂ„nga sessioner pĂ„ repliker, sĂ€rskilt om du har bestĂ€mt dig för att aktivera hot_standby_feedback pĂ„ repliken. För det kan hĂ€nda vad som helst. Vi gav denna replik till en utvecklare för att han skulle testa förfrĂ„gningar. Han skrev en besynnerlig förfrĂ„gan. Startade den och gick för att dricka te, och vi fick en överbelastad Master. Eller vi lĂ€t ett olĂ€mpligt program gĂ„ dit. Situationerna Ă€r olika. Sessioner pĂ„ repliker mĂ„ste övervakas lika noggrant som pĂ„ Master.
  • Och om du har snabba och lĂ„nga förfrĂ„gningar pĂ„ repliker, sĂ„ Ă€r det bĂ€ttre att dela upp dem för belastningsfördelning. Det hĂ€r hĂ€nvisar till streaming_delay. För snabba förfrĂ„gningar, ha en replik med liten replikationsfördröjning. För lĂ„nga rapporteringsförfrĂ„gningar, ha en replik som kan ligga efter med 6 timmar eller en dag. Det Ă€r en helt normal situation.

Vi eliminerar konsekvenserna pÄ samma sÀtt:

  • Vi hittar uppblĂ„sta tabeller.
  • Och komprimerar dem med det mest lĂ€mpliga verktyget för oss.

Den andra historien har nu avslutats. LÄt oss gÄ vidare till den tredje historien.

Vanliga misstag i applikationer som leder till bloat i PostgreSQL. Andrej Salnikov

OcksÄ ganska vanlig för oss, dÀr vi gör en migrering.

Vanliga misstag i applikationer som leder till bloat i PostgreSQL. Andrej Salnikov

  • Varje programprodukt vĂ€xer. Kraven pĂ„ den förĂ€ndras. Vi vill alltid utvecklas. Och ibland hĂ€nder det att vi mĂ„ste uppdatera data i tabellen, genomföra en uppdatering inom ramen för vĂ„r migrering för den nya funktionalitet som vi introducerar i vĂ„r utveckling.
  • Det gamla dataformatet fungerar inte lĂ€ngre. Anta att vi nu gĂ„r till den andra tabellen dĂ€r jag har transaktioner för dessa konton. Och sĂ€g att de var i rubel, men vi har beslutat att öka noggrannheten och göra det i kopecker. För detta behöver vi göra en uppdatering: fĂ€ltet med transaktionssumman multiplicera med hundra.
  • I den moderna vĂ€rlden anvĂ€nder vi automatiserade verktyg för versionskontroll av databaser. LĂ„t oss anta att Liquibase. Vi skriver ner vĂ„r migration dĂ€r. Testar den pĂ„ vĂ„r testdatabas. Allt Ă€r utmĂ€rkt. Uppdateringen lyckas. Det blockerar arbetet under en tid, men vi fĂ„r den uppdaterade datan. Och vi kan köra ny funktionalitet pĂ„ detta. Vi har testat allt, kontrollerat. Allt Ă€r bekrĂ€ftat.
  • Vi genomförde planerat arbete, genomförde migrationen.

Vanliga misstag i applikationer som leder till bloat i PostgreSQL. Andrej Salnikov

HÀr Àr migrationen med uppdateringen presenterad för er. Eftersom detta handlar om transaktioner för konton var tabellen 15 GB. Och eftersom vi uppdaterar varje rad har vi genom uppdateringen fördubblat tabellen, eftersom vi har skrivit över varje rad.

Vanliga misstag i applikationer som leder till bloat i PostgreSQL. Andrej Salnikov

Under migrationen kunde vi inte göra nÄgot med den hÀr tabellen, eftersom alla förfrÄgningar till den köades och vÀntade pÄ att denna uppdatering skulle avslutas. Men hÀr vill jag pÄpeka siffrorna pÄ den vertikala axeln. AlltsÄ hade vi genomsnittlig förfrÄgningstid före migrationen pÄ cirka 5 millisekunder och belastning pÄ processorn, antal blockoperationer för minneslÀsning av disken mindre Àn 7,5.

Vanliga misstag i applikationer som leder till bloat i PostgreSQL. Andrej Salnikov

Vi genomförde migrationen och fick Äterigen problem.

Migrationen lyckades, men:

  • Den gamla funktionaliteten tar lĂ€ngre tid att utföra.
  • Tabellen har Ă„terigen vĂ€xt i storlek.
  • Belastningen pĂ„ servern har Ă„terigen blivit större Ă€n den var.
  • Och naturligtvis, medan vi fortfarande arbetar med den funktionalitet som fungerade bra, har vi förbĂ€ttrat den lite grann.

Och det Àr Äterigen bloat som Äterigen försvÄrar vÄrt liv.

Vanliga misstag i applikationer som leder till bloat i PostgreSQL. Andrej Salnikov

HÀr visar jag att tabellen, precis som i de tidigare tvÄ fallen, inte tÀnker ÄtervÀnda till sina tidigare storlekar. Den genomsnittliga belastningen pÄ servern verkar vara rimlig.

Vanliga misstag i applikationer som leder till bloat i PostgreSQL. Andrej Salnikov

Om vi tittar pÄ tabellen med rÀkningar, sÄ ser vi att den genomsnittliga förfrÄgan har dubblats för denna tabell. Belastningen pÄ processorn och antalet rader som bearbetas i minnet har ökat till över 7,5, jÀmfört med tidigare. För processorerna har det ökat med 2 gÄnger, för blockoperationerna med 1,5 gÄnger, dvs. vi har fÄtt en degradering av serverns prestanda. Och följaktligen Àr det en degradering av prestandan för vÄr applikation. Samtidigt har antalet anrop förblivit ungefÀr pÄ samma nivÄ.

Vanliga misstag i applikationer som leder till bloat i PostgreSQL. Andrej Salnikov

Och det viktigaste hÀr Àr att förstÄ hur man korrekt gör sÄdana migreringar. Och de mÄste göras. Vi gör dessa migreringar ganska ofta.

  • SĂ„dana stora migreringar görs inte automatiskt. De mĂ„ste alltid övervakas.
  • Det behövs kontroll frĂ„n en kunnig person. Om du har en DBA i teamet, lĂ„t denne göra det. Det Ă€r deras jobb. Om inte, sĂ„ bör den mest erfarna personen som vet hur man arbetar med databaser göra det.
  • Den nya databasschemat, Ă€ven om vi uppdaterar en kolumn, förbereder vi alltid i steg, dvs. i förvĂ€g innan den nya versionen av applikationen rullas ut:
  • Nya fĂ€lt lĂ€ggs till dĂ€r vi kommer att lagra de uppdaterade data.
  • Vi flyttar data frĂ„n det gamla fĂ€ltet till det nya fĂ€ltet i smĂ„ delar. Varför gör vi detta? För det första kontrollerar vi alltid processen under den hĂ€r processen. Vi vet att vi redan har flyttat sĂ„ och sĂ„ mĂ„nga batchar och har sĂ„ och sĂ„ mĂ„nga kvar.
  • En annan positiv effekt Ă€r att vi mellan varje sĂ„dan batch stĂ€nger en transaktion, öppnar en ny, och detta ger möjligheten för autovakuumet att arbeta pĂ„ tabellen, mĂ€rka döda rader för Ă„teranvĂ€ndning.
  • För rader som kommer att dyka upp under applikationens gĂ„ng (vĂ„r gamla applikation kör fortfarande) lĂ€gger vi till en trigger som skriver nya vĂ€rden i de nya fĂ€lten. I vĂ„rt fall – det innebĂ€r multiplikation med hundra av det gamla vĂ€rdet.
  • Om vi Ă€r helt envisa och vill ha samma fĂ€lt, sĂ„ vid slutet av alla migreringar och innan vi rullar ut den nya versionen av applikationen, byter vi helt enkelt namn pĂ„ fĂ€lten. De gamla till ett pĂ„hittat namn och de nya fĂ€lten byter vi namn till gamla.
  • Och först efter detta lanserar vi den nya versionen av applikationen.

Och pÄ sÄ sÀtt kommer vi inte att fÄ bloat och vi kommer inte att fÄ en sÀnkning av prestanda.

HĂ€r avslutades den tredje historien.

Vanliga misstag i applikationer som leder till bloat i PostgreSQL. Andrej Salnikov

https://github.com/dataegret/pg-utils/blob/master/sql/table_bloat.sql

https://github.com/dataegret/pg-utils/blob/master/sql/table_bloat_approx.sql

Och nu ska vi gÄ lite mer in pÄ verktygen som jag nÀmnde i den allra första historien.

Innan du börjar leta efter bloat, bör du definitivt installera tillÀgget pgstattuple.

För att ni inte ska behöva hitta pÄ frÄgorna sjÀlva, har vi redan skrivit dessa frÄgor i vÄrt arbete. Ni kan anvÀnda dem. HÀr presenteras tvÄ frÄgor.

  • Den första tar ganska lĂ„ng tid att köra, men den ger dig exakta vĂ€rden för bloat i tabellen.
  • Den andra gĂ„r snabbare och Ă€r mycket effektiv nĂ€r du behöver göra en snabb bedömning – finns det bloat eller inte i tabellen. Och du bör ocksĂ„ förstĂ„ att bloat i en Postgres-tabell alltid finns. Det Ă€r en egenhet av dess MVCC-modell.
  • Och 20 % bloat Ă€r normalt för tabeller i de flesta fall. Det vill sĂ€ga, du behöver inte oroa dig och komprimera denna tabell.

Hur man identifierar tabeller som har svÀllt, det har vi klargjort, sÀrskilt nÀr de har svÀllt med onödiga data.

Nu om hur man ÄtgÀrdar bloat:

  • Om vi har en liten tabell och bra diskar, det vill sĂ€ga för en tabell under en gigabyte gĂ„r det bra att anvĂ€nda VACUUM FULL. Det kommer att ta en exklusiv lĂ„s pĂ„ tabellen i nĂ„gra sekunder och sen klarar det allt snabbt och effektivt. Vad gör VACUUM FULL? Det tar en exklusiv lĂ„s pĂ„ tabellen och kopierar levande rader frĂ„n gamla tabeller till en ny tabell. Och i slutet byter det plats pĂ„ dem. Gamla filer tas bort, nya sĂ€tts istĂ€llet för de gamla. Men under sin operation tar det en exklusiv lĂ„s pĂ„ tabellen. Det betyder att du inte kan göra nĂ„got med denna tabell: varken skriva till den, lĂ€sa frĂ„n den eller modifiera den. Och VACUUM FULL krĂ€ver extra diskutrymme för att lagra data.
  • NĂ€sta verktyg pg_repack. I sin funktion Ă€r det mycket lik VACUUM FULL, eftersom det ocksĂ„ kopierar data frĂ„n gamla filer till nya och byter ut dem i tabellen. Men det tar inte en exklusiv lĂ„s pĂ„ tabellen i början av sin operation, utan gör det först nĂ€r det har fĂ€rdiga data för att byta ut filerna. Diskresurskraven Ă€r liknande VACUUM FULL. Du behöver extra utrymme pĂ„ disken, vilket ibland kan vara kritiskt om du har terabyte-stora tabeller. Och det Ă€r ganska resurskrĂ€vande pĂ„ processorn, eftersom det arbetar aktivt med in- och utdata.
  • Det tredje verktyget Ă€r pgcompacttable. Den hanterar resurser pĂ„ ett mer varsamt sĂ€tt eftersom den fungerar enligt nĂ„got andra principer. HuvudpoĂ€ngen med pgcompacttable Ă€r att den vid uppdateringar flyttar alla levande rader till början av tabellen. Och sedan kör den vacuum pĂ„ denna tabell, eftersom vi vet att vi har levande rader i början och döda rader i slutet. Vacuum skĂ€r sedan bort den svansen, det vill sĂ€ga att det inte krĂ€ver mycket extra diskutrymme. Dessutom kan det ocksĂ„ optimeras för resurser.

Allt med verktygen.

Vanliga misstag i applikationer som leder till bloat i PostgreSQL. Andrej Salnikov

Om du tycker att Àmnet med bloat Àr intressant och vill grÀva djupare, hÀr Àr nÄgra anvÀndbara lÀnkar:

Jag har hÀr försökt att visa en skrÀmselhicka för utvecklarna, eftersom de Àr vÄra direkta kunder till databaser och mÄste förstÄ vilka konsekvenser olika handlingar kan leda till. Jag hoppas att jag lyckades. Tack för uppmÀrksamheten!

FrÄgor

Tack för presentationen! Du pratade om hur man kan identifiera problem. Men hur kan man förhindra dem? Det vill sÀga, jag hade en situation dÀr förfrÄgningar hÀngde inte bara för att de kontaktade externa tjÀnster. Det var bara nÄgra galna joins. Det fanns nÄgra smÄ harmlösa förfrÄgningar som hÀngde i ett dygn och sedan började skapa kaos. Det liknar mycket det du beskriver. Hur kan man övervaka detta? Ska man stÀndigt sitta och kolla vilken förfrÄgan som hÀnger? Hur kan man förhindra detta?

I det hÀr fallet Àr det en uppgift för administratörerna i ditt företag, inte nödvÀndigtvis för DBA.

Jag Àr administratör.

I PostgreSQL finns det en vy som heter pg_stat_activity, dÀr hÀngande förfrÄgningar visas. Och du kan se hur lÀnge den har hÀngt dÀr.

MÄste jag gÄ in och kolla var femte minut?

StÀll in cron och kontrollera. Om du har en lÄngvarig begÀran, skriv ett mail och allt. Det vill sÀga, du behöver inte titta med ögonen, det gÄr att automatisera. Du fÄr ett mail, och du reagerar pÄ det. Eller sÄ kan du avfyra det automatiskt.

Finns det uppenbara orsaker till varför detta hÀnder?

Jag har nÀmnt nÄgra. Andra mer komplexa exempel. Och diskussionen kan ta lÄng tid.

Tack för presentationen! Jag ville klargöra kring verktyget pg_repack. Om det inte gör en exklusiv lĂ„sning, dÄ 

Det gör en exklusiv lÄsning.


 ...kan jag potentiellt förlora data. Ska min applikation inte registrera nĂ„got under den tiden?

Nej, den fungerar lugnt med tabellen, det vill sÀga pg_repack flyttar först alla levande rader som finns. SjÀlvklart sker det nÄgon registrering i tabellen. Den lÀgger bara till den sista biten.

Det vill sÀga, gör den i slutÀnden faktiskt?

I slutet tar den en exklusiv lÄsning för att byta plats pÄ de hÀr filerna.

Kommer det att gÄ snabbare Àn VACUUM FULL?

VACUUM FULL, nÀr det startade, tog direkt en exklusiv lÄsning. Och förrÀn den har gjort allt, slÀpper den den inte. Och pg_repack tar en exklusiv lÄsning endast vid tidpunkten för filbyten. Just dÄ kan du inte skriva dit, men alla data gÄr inte förlorade, allt kommer att vara i ordning.

Hej! Du pratade om hur autovacuum fungerar. Det fanns en graf med röda, gula och gröna celler. Det vill sĂ€ga, de gula – han markerade dem som raderade. Och följaktligen kan man skriva nĂ„got nytt i dem?

Ja. Postgres tar inte bort rader. Det Àr dess specifikation. Om vi uppdaterar en rad, markerar vi den gamla som raderad. DÀr sÀtts id för transaktionen som Àndrade den raden, och vi skriver in en ny rad. Och vi har sessioner som potentiellt kan lÀsa dem. Vid nÄgon tidpunkt blir de helt gamla. Och syftet med autovacuum Àr att den gÄr igenom dessa rader och markerar dem som onödiga. Och dit kan man skriva om data.

Jag förstÄr. Men frÄgan handlar lite inte om det. Jag har inte avslutat. LÄt oss anta att vi har en tabell. Den har fÀlt med variabel storlek. Och om jag försöker sÀtta in nÄgot nytt kan det kanske inte fÄ plats i den gamla cellen.

Nej, hela raden uppdateras oavsett. Postgres har tvÄ datalagermodeller. Den vÀljer baserat pÄ datatyp. Det finns data som lagras direkt i tabellen, och sÄ finns det tos-data. Det handlar om stora datamÀngder: text, json. De lagras i separata tabeller. Och i dessa tabeller hÀnder samma sak med bloat, det vill sÀga exakt samma sak. De Àr bara separerade.

Tack för presentationen! Hur acceptabelt Àr det att anvÀnda statement timeout för att begrÀnsa lÀngden pÄ förfrÄgningar?

Mycket acceptabelt. Vi anvÀnder det överallt. Och eftersom vi inte har vÄra egna tjÀnster, utan erbjuder fjÀrrsupport, sÄ finns det en ganska varierad kundbas. Alla Àr ganska nöjda med det. Det finns cron-jobb som gör kontroller. Det diskuteras helt enkelt lÀngden pÄ sessionerna med kunden, innan vi avslutar dem. Det kan vara en minut, det kan vara 10 minuter. Det beror pÄ belastningen pÄ databasen och dess syfte. Men vi anvÀnder pg_stat_activity för alla.

Tack för presentationen! Jag försöker anpassa din presentation till mina applikationer. Och det verkar som om vi alltid startar en transaktion, och alltid avslutar den. Om nÄgot undantag intrÀffar, sÄ sker rollback ÀndÄ. Och hÀr började jag fundera. En transaktion kan ju startas implicit. Det Àr nog en vink till tjejen. Om jag bara gör en uppdatering av en post, startar transaktionen i PostgreSQL och avslutas den först nÀr anslutningen kopplas ur?

Om du pratar om applikationsnivÄn nu, sÄ beror det pÄ vilken drivrutin du anvÀnder, vilken ORM som anvÀnds. Det finns mycket instÀllningar. Om auto commit Àr aktiverat dÄ startar och avslutas transaktionen direkt.

Det vill sÀga, avslutas den genast efter uppdateringen?

Det beror pÄ instÀllningarna. Jag nÀmnde en instÀllning. Denna auto commit. Den Àr ganska utbredd. Om den Àr aktiverad sÄ öppnas och stÀngs transaktionen. Om du inte uttryckligen sa "start transaction" och "end transaction", utan bara körde en frÄga i sessionen.

Hej! Tack för presentationen! TÀnk att vi har en databas som vÀxer och vÀxer och nu tar det slut pÄ utrymmet pÄ servern. Finns det nÄgra verktyg för att ÄtgÀrda denna situation?

Utrymmet pÄ servern bör helst övervakas.

Till exempel, om DBA fÄr en kopp kaffe, var pÄ semester, osv.

NÀr ett filsystem skapas, sÄ reserveras Ätminstone en del utrymme dÀr inga data skrivs.

Och om det blir helt noll?

Det kallas reserverat utrymme, vilket innebÀr att det kan frigöras och beroende pÄ hur stort det Àr, sÄ fÄr ni ledigt utrymme. Jag vet inte hur mycket det Àr som standard. I ett annat fall kan man behöva leverera diskar för att ha tillrÀckligt med utrymme för att utföra ÄterstÀllningsoperationen. Man kan ta bort en tabell som man garanterat inte behöver.

Finns det andra verktyg?

Det Àr alltid manuellt arbete. Man ser pÄ plats vad som Àr bÀst att göra, eftersom det finns kritiska och icke-kritiska data. Och för varje databas och tillÀmpning som arbetar med den beror det pÄ företaget. Beslutet fattas alltid pÄ plats.

Tack för presentationen! Jag har tvÄ frÄgor. För det första, ni visade bilder dÀr ni visade att vid hÀngande transaktioner ökar bÄde storleken pÄ tabellutrymmet och storleken pÄ indexet. Och lÀngre fram i presentationen fanns mÄnga verktyg som packar tabellen. Men vad hÀnder med indexet?

De packar ocksÄ.

Men vakuum pÄverkar inte indexet?

Vissa verktyg arbetar med indexet. Till exempel pg_rapack, pgcompacttable. Vakuum Äterskapar index, det pÄverkar dem. Syftet med VACUUM FULL Àr att skriva om allt, det arbetar med allt.

Och den andra frÄgan. Jag förstod inte varför rapporter pÄ repliker sÄ starkt beror pÄ sjÀlva replikeringen. Jag hade för mig att rapporter Àr lÀsning och replikering Àr skrivning.

Var uppstÄr konflikten vid replikering? Vi har en Master dÀr processerna sker. Vi har en autovakuumprocess. Vad gör autovakuum egentligen? Det tar bort gamla rader. Om vi har en begÀran pÄ repliken under tiden som lÀser dessa gamla rader, och pÄ Master har det hÀnt att autovakuum markerat dessa rader som möjliga för överskrivning, sÄ har vi skrivit om dem. NÀr ett paket data kommer och vi mÄste skriva om de rader som begÀran pÄ repliken behöver, dÄ kommer replikationsprocessen att vÀnta pÄ den timeout ni har stÀllt in. Sedan kommer PostgreSQL att avgöra vad som Àr viktigare för den. Och replikeringen Àr viktigare Àn begÀran, och den kommer att avbryta begÀran för att genomföra dessa Àndringar pÄ repliken.

Andrey, jag har en frĂ„ga. Är de hĂ€r fantastiska diagrammen du visade under presentationen resultatet av nĂ„got av dina verktyg? Hur konstruerades diagrammen?

Detta Àr en tjÀnst Okmeter.

Är detta en kommersiell produkt?

Ja. Det Àr en kommersiell produkt.

KĂ€lla: habr.com

Köp pĂ„litlig webbhotell med DDoS-skydd, VPS VDS-servrar đŸ”„ Köp pĂ„litlig webbhotell med DDoS-skydd, VPS VDS-servrar | ProHoster