Uobičajene greške u aplikacijama koje dovode do bloat-a u PostgreSQL-u. Andrey Salkinov

Predlažem da se upoznate s transkripcijom izlaganja iz početka 2016. godine Andreyja Salkinova "Uobičajene greške u aplikacijama koje dovode do bloat-a u PostgreSQL-u"

U ovom izlaganju ću obraditi osnovne greške u aplikacijama koje se javljaju u fazi projektiranja i pisanja aplikativnog koda. Fokusiraću se samo na one greške koje dovode do bloat-a u PostgreSQL-u. Obično to označava početak kraja performansi vašeg sistema u celini, iako na prvi pogled nisu postojale nikakve naznake za to.

Uobičajene greške u aplikacijama koje dovode do bloat-a u PostgreSQL-u. Andrey Salkinov

Drago mi je da vas sve pozdravim! Ovo izlaganje nije toliko tehničko kao prethodno od mog kolege. Ovo izlaganje je prvenstveno usmereno na razvijatelje backend sistema, jer imamo dosta klijenata. I svi oni prave iste greške. O tome ću vam pričati. Objasniću vam do kakvih katastrofalnih i loših posledica vode te greške.

Uobičajene greške u aplikacijama koje dovode do bloat-a u PostgreSQL-u. Andrey Salkinov

Zašto se greške događaju? Događaju se iz dva razloga: zbog neodgovornog pristupa, nadajući se da će to možda proći, i zbog nepoznavanja mehanizama koji se odvijaju na nivoima između baze podataka i aplikacije, kao i unutar same baze.

Pokazaću vam tri primera s groznim slikama o tome kako je sve postalo loše. Ukratko ću objasniti mehanizam koji se događa. I kako se boriti protiv tih problema kada se dogode, kao i koje preventivne metode koristiti za sprečavanje grešaka. Govoriću o pomoćnim alatima i dati korisne linkove.

Uobičajene greške u aplikacijama koje dovode do bloat-a u PostgreSQL-u. Andrey Salkinov

Koristio sam testnu bazu podataka, gde sam imao dve tabele. Jedna tabela je sa računima klijenata, druga s operacijama na tim računima. S vremena na vreme ažuriramo stanje na tim računima.

Uobičajene greške u aplikacijama koje dovode do bloat-a u PostgreSQL-u. Andrey Salkinov

Izvorni podaci tabele: ona je dovoljno mala, 2 MB. Vreme odgovora za bazu i konkretno za tu tabelu je takođe vrlo dobro. Dobar je i pritisak – 2000 operacija u sekundi na tabeli.

Uobičajene greške u aplikacijama koje dovode do bloat-a u PostgreSQL-u. Andrey Salkinov

Kroz ovo izlaganje ću vam prikazati grafike kako bi bilo jasno šta se događa. Uvek će biti 2 slajda s grafikonima. Prvi slajd – to je ono što se događa u opštem smislu na serveru.

U ovoj situaciji vidimo da imamo tabelu male veličine. Indeks je mali, 2 MB. To je prvi graf s leve strane.

Prosečno vreme odgovora na serveru takođe je stabilno i malo. To je gornji desni graf.

Donji lijevi grafikon prikazuje najdulje transakcije. Vidimo da se transakcije brzo izvršavaju. I automatska vakuum funkcija još nije aktivna, jer je ovo bio testni start. U budućnosti će raditi i bit će nam koristan.

Uobičajene greške u aplikacijama koje dovode do bloat-a u PostgreSQL-u. Andrey Salkinov

Drugi slajd uvijek će biti posvećen ispitivanoj tablici. U ovoj situaciji neprekidno ažuriramo zalihe na računima klijenta. I vidimo da je prosječno vrijeme odziva za operaciju ažuriranja prilično dobro, manje od milisekunde. Primjećujemo također da resursi procesora (to je gornji desni grafikon) također ravnomjerno troše i to na razmjerno maloj razini.

Gornji desni grafikon pokazuje koliko operativne i diskovne memorije koristimo u potrazi za potrebnim redom, prije nego što ga ažuriramo. Broj operacija po tablici je 2,000 u sekundi, kao što sam spomenuo na početku.

Uobičajene greške u aplikacijama koje dovode do bloat-a u PostgreSQL-u. Andrey Salkinov

A sada se događa tragedija. Iz nekog razloga javlja se duga zaboravljena transakcija. Razlozi su obično prozaični:

  • Jedan od najčešćih razloga je taj što smo u kodu aplikacije počeli obraćati se vanjskom servisu. I taj servis nam ne odgovara. To jest, otvorili smo transakciju, promijenili bazu i otišli čitati poštu ili se obratili drugom servisu unutar naše infrastrukture, koji nam iz nekog razloga ne odgovara. I imamo zaključanu sesiju u stanju - ne zna se kada će se razriješiti.
  • Druga situacija nastaje kada je u našem kodu iz nekog razloga došlo do iznimke. I u iznimci nismo obradili zatvaranje transakcije. Tako da imamo visoko stanje sesije s otvorenom transakcijom.
  • I posljednji - to je također prilično čest slučaj. To je nekvalitetan kod. Neki okviri otvaraju transakciju. Ona visi, a možete u aplikaciji ne znati da ona visi.

K čemu dovode ovakve stvari?

Do toga da se naše tablice i indeksi počinju naglo povećavati. Ovo je točno taj efekt bloat. Za bazu to će značiti da će se vrlo naglo povećati vrijeme odgovora baze podataka, povećat će se opterećenje na serveru baze podataka. I kao rezultat toga, naše će aplikacije trpjeti. Jer ako ste u kodu trošili 10 milisekundi na upit u bazu, 10 milisekundi na svoju logiku, tada je vaša funkcija radila 20 milisekundi. A sada će vaša situacija biti potpuno tužna.

Pogledajmo što se događa. Donji lijevi grafikon pokazuje da imamo dugotrajnu transakciju. Ako pogledamo gornji lijevi grafikon, vidimo da je veličina tablice s dva megabajta naglo porasla na 300 megabajta. Pri tome se broj podataka u tablici nije promijenio, tj. u njoj se nalazi prilično velika količina otpada.

Uobičajene greške u aplikacijama koje dovode do bloat-a u PostgreSQL-u. Andrey Salkinov

Sveukupna situacija po srednjem vremenu odgovora poslužitelja također se promijenila na nekoliko redova veličine. Dakle, svi upiti prema poslužitelju počeli su drastično usporavati. U međuvremenu, pokrenuli su se unutarnji procesi Postgresa u obliku automatske vakuumacije, koji pokušavaju nešto učiniti i troše resurse.

Uobičajene greške u aplikacijama koje dovode do bloat-a u PostgreSQL-u. Andrey Salkinov

Što se događa s našom tablicom? Ista stvar. Prosječno vrijeme odgovora na tablicu naglo je poraslo. Ako govorimo o potrošnji resursa, vidimo da je opterećenje procesora znatno povećano. To je na gornjem desnom grafikonu. Povećano je zato što procesor mora pregledavati hrpu beskorisnih redaka u potrazi za jednim potrebnim. To je na donjem desnom grafikonu. Kao rezultat, broj poziva po sekundi počeo je naglo opadati, jer baza ne uspijeva obraditi isti broj upita.

Uobičajene greške u aplikacijama koje dovode do bloat-a u PostgreSQL-u. Andrey Salkinov

Moramo se vratiti u život. Ulazimo na internet i saznajemo da dugotrajne transakcije dovode do problema. Nalazimo i ubijamo tu transakciju. I sve se vraća u normalu. Sve radi kako treba.

Smirili smo se, ali nakon nekog vremena počinjemo primjećivati da aplikacija ne radi kako je radila prije incidenta. Upiti se i dalje obrađuju sporije, i to značajno sporije. U mom slučaju, oko jedan i pol do dva puta sporije. Opterećenje na poslužitelju također je veće nego što je bilo prije incidenta.

Uobičajene greške u aplikacijama koje dovode do bloat-a u PostgreSQL-u. Andrey Salkinov

Pitanje je: "Što se događa s bazom u tom trenutku?" A u bazi se događa sljedeća situacija. Na grafikonu transakcija vidite da je stala i doista nema dugotrajnih transakcija. No veličine tablice tijekom incidenta su katastrofalno narasle. I od tada se nisu smanjile. Prosječno vrijeme u bazi se stabiliziralo. Odgovori izgledaju razmjerno normalno s prihvatljivom brzinom za nas. Automatska vakuumacija postala je aktivnija i počela je nešto raditi s tablicom jer mora obraditi veću količinu podataka.

Uobičajene greške u aplikacijama koje dovode do bloat-a u PostgreSQL-u. Andrey Salkinov

Specifično za testiranu tablicu s računima, gdje mijenjamo ostatke: vrijeme odgovora na upit čini se da se vratilo u normalu. No, zapravo je 1,5 puta više.

I po opterećenju na procesoru vidimo da opterećenje na procesoru nije dosegnulo potrebnu razinu do incidenta. Razlozi su upravo u donjem desnom grafikonu. Vidljivo je da se ondje događa prekomjerna upotreba nekih resursa memorije. Dakle, za pronalaženje potrebnog retka trošimo server resurse baze podataka pretražujući beskorisne podatke. Broj transakcija u sekundi se stabilizirao.

Općenito dobro, ali situacija je gora nego prije. Očita degradacija baze podataka kao posljedica naše aplikacije koja radi s tom bazom podataka.

Uobičajene greške u aplikacijama koje dovode do bloat-a u PostgreSQL-u. Andrey Salkinov

I kako bismo razumjeli što se događa, ako niste bili na prethodnom izlaganju, malo teorije. Teorija o unutarnjem procesu. Zašto je automatska vakuumacija potrebna i što ona radi?

Ukratko, za razumijevanje. U jednom trenutku imamo tablicu. U tablici imamo retke. Ti retci mogu biti aktivni, živi, potrebni nam sada. Na slici su označeni zelenom bojom. A postoje mrtvi retci, koji su već obrađeni, ažurirani, na njima su nastale nove stavke. I oni su označeni da više nisu zanimljivi bazi podataka. No, ostaju u tablici zbog posebnosti Postgres-a.

Zašto je potrebna automatska vakuumacija? Automatska vakuumacija u nekom trenutku dolazi, obraća se bazi podataka i pita je: "Daj mi, molim te, ID najstarije transakcije koja je trenutno otvorena u bazi podataka." Baza podataka vraća taj ID. A automatska vakuumacija, oslanjajući se na njega, prolazi kroz retke u tablici. Ako vidi da su neki retci izmijenjeni mnogo starijim transakcijama, onda ima pravo označiti ih kao retke koje možemo ponovno koristiti u budućnosti, zapisujući nove podatke. To je pozadinski proces.

U tom trenutku nastavljamo raditi s bazom podataka, nastavljamo vršiti neke promjene u tablici. I na te retke koje možemo ponovno koristiti, zapisujemo nove podatke. Tako da imamo kružnu ekonomiju, tj. stalno se pojavljuju neki stari mrtvi retci, umjesto njih zapisujemo nove retce koji su nam potrebni. I to je normalno stanje za rad PostgreSQL-a.

Uobičajene greške u aplikacijama koje dovode do bloat-a u PostgreSQL-u. Andrey Salkinov

Što se dogodilo tijekom nesreće? Kako je taj proces tekao?

Imali smo tablicu u nekom stanju, neki su redovi bili aktivni, neki ne. Došao je autotvacuum. Pitao je bazu podataka koja je naša najstarija transakcija i koji joj je ID. Dobio je taj ID, koji može biti star nekoliko sati ili nekoliko minuta. To ovisi o tome koliki je pritisak na vašoj bazi podataka. I onda je krenuo tražiti redove koje može označiti kao ponovno upotrebljive. I nije pronašao takve redove u našoj tablici.

Ali mi u tom trenutku nastavljamo raditi s tablicom. Radimo nešto, ažuriramo, mijenjamo podatke. A što baza podataka u to vrijeme radi? Nema joj druge nego dodavati nove redove na kraj postojeće tablice. Tako da nam se veličina tablice počinje povećavati.

U stvarnosti su nam potrebni zeleni redovi za rad. Ali tijekom takvih problema dobivamo da je postotak zelenih redova izuzetno nizak u cijelom volumenu tablice.

Kada izvršavamo upit, bazi podataka treba proći kroz sve redove: i crvene i zelene, da pronađe potrebni red. Efekt povećanja tablice beskorisnim podacima naziva se „bloat“, koji također troši naš prostor na disku. Sjećate se, bilo je 2 MB, postalo je 300 MB? A sada zamijenite megabajte gigabajtima i brzo ćete izgubiti sve svoje diskovne resurse.

Uobičajene greške u aplikacijama koje dovode do bloat-a u PostgreSQL-u. Andrey Salkinov

Koje posljedice mogu biti za nas?

  • U mom primjeru, tablica i indeks su narasli 150 puta. Neki od naših klijenata su imali još teže situacije kada bi prostor na disku počeo ponestajati.
  • Veličina tablica sama po sebi nikada neće opasti. Autovacuum ponekad može odrezati rep tablice ako su tu samo mrtvi redovi. No, budući da se stalno događa rotacija, jedan zeleni red može zapeći na kraju i ne ažurirati se, dok će svi ostali biti upisani negdje na početku tablice. No, to je toliko malo vjerojatno da će se vaša tablica smanjiti, tako da nije realno očekivati.
  • Bazi podataka treba proći kroz cijeli niz beskorisnih redova. Trošimo diskovne resurse, trošimo resurse procesora i energiju.
  • I to izravno utječe na našu aplikaciju, jer ako smo na početku trošili 10 milisekundi na upit, 10 milisekundi na naš kod, tijekom akcidenta smo počeli trošiti sekundu na upit i 10 milisekundi na kod, tj. performanse aplikacije su se smanjile red veličine. A kada je akcident otklonjen, počeli smo trošiti 20 milisekundi na upit i 10 milisekundi na kod. To znači da smo ipak pali 1,5 puta u performansama. I to sve zbog jedne transakcije koja je zapela, možda čak i zbog naše pogreške.
  • I pitanje je: „Kako sve vratiti natrag?“, da se sve vrati u normalu i da upiti budu jednako brzi kao prije incidenta.

Uobičajene greške u aplikacijama koje dovode do bloat-a u PostgreSQL-u. Andrey Salkinov

Za to postoji određeni ciklus radnji koji se provodi.

Prvo, potrebno je pronaći problematične tablice koje su se proširile. Shvaćamo da se za neke tablice zapisivanje odvija aktivnije, dok se za neke odvija manje aktivno. I za to se koristi proširenje pgstattuple. Instaliranjem ovog proširenja možete napisati upite koji će vam pomoći pronaći tablice koje su se značajno proširile.

Nakon što pronađete te tablice, potrebno ih je sažeti. Za to postoje alati. U našoj tvrtki koristimo tri alata. Prvi je ugrađeni VACUUM FULL. On je nemilosrdan, strog i surov, ali ponekad je vrlo koristan. Pg_repack i pgcompacttable – to su vanjski alati za sažimanje tablica. I oni se više brinu o bazi podataka.

Koriste se ovisno o tome što vam više odgovara. No, o tome ću govoriti na kraju. Glavno je da postoje tri alata. Ima izbora.

Nakon što smo sve ispravili, osigurali se da je sve dobro, moramo znati kako spriječiti ovu situaciju u budućnosti:

  • Sprječava se relativno lako. Potrebno je pratiti trajanje sesija na Master serveru. Posebno opasne sesije su one u stanju idle in transaction. To su one koje su otvorile transakciju, nešto napravile i otišle ili su jednostavno zapela, izgubila se u kodu.
  • I za vas, kao programere, važno je testirati kod na trenutak nastanka ovih situacija. To nije teško učiniti. To će biti korisna provjera. Izbjeći ćete veliki broj "dječjih" problema povezanih s dugim transakcijama.

Uobičajene greške u aplikacijama koje dovode do bloat-a u PostgreSQL-u. Andrey Salkinov

Na ovim grafikonima želim vam pokazati kako se promijenila tablica i ponašanje baze podataka nakon što sam u ovom slučaju izvršio VACUUM FULL na tablici. To nije proizvodnja.

Veličina tablice odmah se vratila u normalno radno stanje od nekoliko megabajta. Na prosječno vrijeme odgovora na serveru to nije imalo velikog utjecaja.

Uobičajene greške u aplikacijama koje dovode do bloat-a u PostgreSQL-u. Andrey Salkinov

No, konkretno po našoj ispitu tablici, gdje smo ažurirali stanje na računima, vidimo da se prosječno vrijeme odgovora na zahtjev za ažuriranjem podataka u tablici smanjilo na prekriznu razinu. Resursi koje procesor troši za izvršavanje ovog zahtjeva također su pali na prekriznu razinu. A donji desni grafikon pokazuje da sada nalazimo upravo onaj red koji nam treba odmah, bez pretraživanja hrpe mrtvih redova koji su postojali prije kompresije tablice. I prosječno vrijeme zahtjeva ostalo je otprilike na istoj razini. No, tu imam više grešku u svom hardveru.

Uobičajene greške u aplikacijama koje dovode do bloat-a u PostgreSQL-u. Andrey Salkinov

Ovdje završava prva priča. To je najčešća priča. I događa se svima, bez obzira na iskustvo klijenta, koliko su tamo kvalificirani programeri. Pr sooner ili kasnije to se dogodi.

Druga priča, u kojoj raspoređujemo opterećenje i optimiziramo servere.

Uobičajene greške u aplikacijama koje dovode do bloat-a u PostgreSQL-u. Andrey Salkinov

  • Već smo odrasli i postali ozbiljni dečki. I shvaćamo da imamo replikaciju i dobro bi nam došlo da uravnotežimo opterećenje: pisati na Master, a čitati s replike. Obično ova situacija nastaje kada želimo pripremati izvještaje ili ETL. I poslovanje je tome jako zadovoljno. Jako želi razne izvještaje s hrpom složene analitike.
  • Izvještaji traju satima, jer se složena analitika ne može izračunati u milisekundama. Kao hrabri dečki, pišemo kod. U aplikaciji pravimo umetanja, tako da zapisujemo na Master, a izvještaje izvršavamo na repliki.
  • Raspoređujemo opterećenje.
  • Sve radi odlično. Mi smo odlični.

Uobičajene greške u aplikacijama koje dovode do bloat-a u PostgreSQL-u. Andrey Salkinov

Kako ta situacija izgleda? Konkretno na ovim grafikonima dodao sam trajanje transakcija s replike. Svi ostali grafikon odnosni su samo na Master server.

Izvještajna tablica sada je postala veća. Ima ih više. Vidimo da je prosječno vrijeme odgovora poslužitelja stabilno. Primjećujemo da imamo dugotrajnu transakciju na replici koja traje 2 sata. Vidimo miran rad automatskog vakuuma koji obrađuje mrtve redove. I sve je u redu.

Uobičajene greške u aplikacijama koje dovode do bloat-a u PostgreSQL-u. Andrey Salkinov

Specifično za testiranu tablicu nastavljamo ažurirati salda na računima. Također imamo stabilno vrijeme odgovora na zahtjeve, stabilnu potrošnju resursa. Sve je u redu.

Uobičajene greške u aplikacijama koje dovode do bloat-a u PostgreSQL-u. Andrey Salkinov

Sve je dobro dok se ti izvještaji ne počnu ispaljivati zbog sukoba s replikacijom. I ispaljuju se s konstantnom učestalošću.

Pretražujemo internet i počinjemo čitati zašto se to događa. Pronalazimo rješenja.

Prvo rješenje je povećati kašnjenje replikacije. Znamo da naš izvještaj radi 3 sata. Postavljamo kašnjenje replikacije na 3 sata. Pokrećemo sve, ali problemi s izvještajima i dalje traju.

Želimo da sve bude savršeno. Idemo dalje. I nalazimo izvrsnu postavku na internetu – hot_standby_feedback. Uključujemo ga. Hot_standby_feedback nam omogućuje da zadržimo rad automatskog vakuuma na Masteru. Tako se potpuno oslobađamo sukoba replikacije. I sve nam dobro radi s izvještajima.

Uobičajene greške u aplikacijama koje dovode do bloat-a u PostgreSQL-u. Andrey Salkinov

A što se to događa s našim Master poslužiteljem u to vrijeme? Na Master poslužitelju se događa potpuna katastrofa. Trenutno promatramo grafove kada sam uključio obje te postavke. I vidimo da je sesija na replici na neki način počela utjecati na situaciju na Master poslužitelju. Doista utječe jer je obustavila automatski vakuum koji čisti mrtve redove. Veličina tablice ponovno je naglo porasla. Prosječno vrijeme izvršavanja upita kroz cijelu bazu podataka također se naglo povećalo. Automatski vakuumi su se malo napregnuli.

Uobičajene greške u aplikacijama koje dovode do bloat-a u PostgreSQL-u. Andrey Salkinov

Specifično za našu tablicu vidimo da je i ažuriranje podataka skočilo u nebesa. Potrošnja procesorskih resursa također se značajno povećala. Ponovno pretražujemo veliko množstvo mrtvih beskorisnih redova. I vrijeme odgovora na ovu tablicu, broj transakcija opao je.

Uobičajene greške u aplikacijama koje dovode do bloat-a u PostgreSQL-u. Andrey Salkinov

Kako će to izgledati ako ne znamo o čemu sam govorio do sada?

  • Započinjemo s pronalaženjem problema. Ako smo se susretali s problemima u prvom dijelu, znamo da bi razlog mogla biti dugačka transakcija i išli bismo na Master. Problem imamo na Masteru. Sviđa se njemu. Zagrijava se, Load Average mu je blizu stotke.
  • Zahtjevi su tamo usporeni, ali ne vidimo nikakve dugotrajne transakcije. I ne razumijemo u čemu je problem. Ne znamo gdje tražiti.
  • Provjeravamo serversku opremu. Možda nam je RAID propao. Možda je memorijska traka pregorjela. Što god može biti. No, ne, serveri su novi, sve radi odlično.
  • Svi trče: administratori, programeri i direktor. Ništa ne pomaže.
  • I u nekom trenutku sve iznenada počinje samo od sebe ispravljati.

Uobičajene greške u aplikacijama koje dovode do bloat-a u PostgreSQL-u. Andrey Salkinov

Na replici nam je u to vrijeme zahtjev odrađen i otišao. Dobili smo izvještaj. Posao je još uvijek zadovoljan. Kao što vidimo, tablica nam je opet narasla i ne planira se smanjiti. Na grafikonu sa sesijama ostavio sam komadić ove duge transakcije s replike, kako biste mogli procijeniti koliko dugo traje dok se situacija stabilizira.

Sesija je otišla. I tek nakon nekog vremena server dolazi više-manje u red. I prosječno vrijeme odgovora na zahtjeve na Master serveru dolazi u normu. Jer, konačno, auto-vakuum je dobio priliku da očisti, označi te mrtve retke. I on je počeo raditi svoj posao. I koliko brzo radi, toliko brzo ćemo doći u red.

Uobičajene greške u aplikacijama koje dovode do bloat-a u PostgreSQL-u. Andrey Salkinov

Na ispitnoj tablici, gdje ažuriramo stanje računa, vidimo potpuno istu sliku. Prosječno vrijeme ažuriranja računa također se postupno normalizira. Resursi koje procesor troši također se smanjuju. I broj transakcija u sekundi se vraća u normu. No opet, ne u normu kakva je bila prije kvara.

Uobičajene greške u aplikacijama koje dovode do bloat-a u PostgreSQL-u. Andrey Salkinov

U svakom slučaju, dobijamo pad performansi kao u prvom slučaju od jedan i pol do dva puta, a ponekad i više.

Izgleda da smo učinili sve ispravno. Rasporedili smo opterećenje. Oprema ne miruje. Razumno smo raspodijelili zahtjeve, ali svejedno je ispalo loše.

  • Ne uključujte hot_standby_feedback? Da, ne preporučuje se uključivanje bez posebnih razloga. Ova opcija izravno utječe na glavnog poslužitelja i pauzira rad automatske vakuumske operacije. Ako ga uključite na nekoj replici i zaboravite na to, možete oštetiti glavnog i dobiti velike probleme s aplikacijom.
  • Povećati max_standby_streaming_delay? Da, to je točno za izvještaje. Ako imate tročasovni izvještaj i ne želite da se prekine zbog sukoba repliciranja, jednostavno povećajte kašnjenje. Dugi izvještaji nikada ne zahtijevaju podatke koji su došli u bazu upravo sada. Ako je tročasovni, to znači da ga pokrećete za neki stari period podataka. I za vas, da li imate tri sata kašnjenja ili šest, neće igrati veliku ulogu, ali ćete stabilno primati izvještaje bez problema s njihovim prekidom.
  • Naravno, potrebno je kontrolirati duge sesije na replikama, posebno ako ste odlučili uključiti hot_standby_feedback na replici. Jer može se dogoditi bilo što. Dali ste tu replicu programeru da testira upite. Napisao je nevjerojatan upit. Pokrenuo je i otišao piti kavu, a mi smo dobili zauzetog glavnog. Ili smo pustili neotu aplikaciju. Situacije su razne. Sesije na replikama potrebno je kontrolirati jednako pažljivo kao i na glavnom.
  • I ako imate brze i duge upite na replikama, u tom slučaju je bolje za raspodjelu opterećenja razdvojiti ih. Ovo se odnosi na streaming_delay. Za brze, imajte jednu replikaciju s malim kašnjenjem replikacije. Za duge izvještajne upite imajte replikaciju koja može kasniti 6 sati, pa čak i do jednog dana. To je sasvim normalna situacija.

Uklanjamo posljedice na isti način:

  • Nalazimo napuhane tablice.
  • I komprimiramo ih najprikladnijim alatom koji nam odgovara.

Druga priča ovdje završava. Idemo na treću priču.

Uobičajene greške u aplikacijama koje dovode do bloat-a u PostgreSQL-u. Andrey Salkinov

Također prilično uobičajena za nas, u kojoj radimo migraciju.

Uobičajene greške u aplikacijama koje dovode do bloat-a u PostgreSQL-u. Andrey Salkinov

  • Svaki softverski proizvod raste. Promjenjuju se zahtjevi za njim. Uvijek želimo napredovati. I događa se da je ponekad potrebno ažurirati podatke u tablici, točno pokrenuti ažuriranje u okviru naše migracije za novu funkcionalnost koju uvodimo kao dio našeg razvoja.
  • Stari format podataka nam ne odgovara. Pretpostavimo da se sada obraćamo drugoj tablici, gdje imam operacije po tim računima. I, pretpostavimo, da su bile u rubaljima, a mi smo odlučili povećati točnost i raditi u kopejkama. I za to trebamo napraviti ažuriranje: polje sa iznosom operacije pomnožiti sa sto.
  • U današnjem svijetu koristimo automatizirane alate za kontrolu verzija baza podataka. Pretpostavljam, Liquibase. Upisujemo našu migraciju. Testiramo je na našoj testnoj bazi. Sve je u redu. Ažuriranje prolazi. Blokira rad na neko vrijeme, ali tako dobivamo ažurirane podatke. I možemo pokrenuti novu funkcionalnost na tome. Sve je testirano, provjereno. Sve je potvrđeno.
  • Proveli smo planirane radove, izvršili migraciju.

Uobičajene greške u aplikacijama koje dovode do bloat-a u PostgreSQL-u. Andrey Salkinov

Evo migracije s ažuriranjem predstavljene pred vama. Kako su to operacije po računima, tablica je imala 15 GB. I budući da ažuriramo svaki redak, povećali smo tablicu na dvostruko, jer smo prepisali svaki redak.

Uobičajene greške u aplikacijama koje dovode do bloat-a u PostgreSQL-u. Andrey Salkinov

Tijekom migracije nismo mogli raditi s ovom tablicom, jer su svi upiti prema njoj čekali u redu i čekali da se to ažuriranje završi. No, ovdje želim skrenuti vašu pozornost na brojke koje se nalaze na vertikalnoj osi. Odnosno, imamo prosječno vrijeme upita prije migracije oko 5 milisekundi i opterećenje na procesoru, broj blokovskih operacija čitanja memorije diska je manji od 7,5.

Uobičajene greške u aplikacijama koje dovode do bloat-a u PostgreSQL-u. Andrey Salkinov

Izvršili smo migraciju i ponovo dobili probleme.

Migracija je prošla uspješno, ali:

  • Stara funkcionalnost postala je sporija.
  • Tablica se ponovo povećala u veličini.
  • Opterećenje na serveru ponovo je postalo veće nego što je bilo.
  • I, naravno, još uvijek se bavimo onom funkcionalnošću koja je dobro radila, malo smo je poboljšali.

I to je ponovo bloat koji nam opet kvari život.

Uobičajene greške u aplikacijama koje dovode do bloat-a u PostgreSQL-u. Andrey Salkinov

Ovdje pokazujem da se tablica, kao i u prethodna dva slučaja, ne planira vraćati na prethodne veličine. Prosječno opterećenje na serveru izgleda razmjerno.

Uobičajene greške u aplikacijama koje dovode do bloat-a u PostgreSQL-u. Andrey Salkinov

Ako se obratimo tablici sa računima, vidjet ćemo da je prosječno vrijeme zahtjeva dvostruko poraslo u odnosu na tu tablicu. Opterećenje na procesor i broj pretraživanih redova u memoriji skočili su iznad 7,5, a prije su bili ispod. Skočilo je dvostruko u slučaju procesora, a u slučaju blok operacija 1,5 puta, tj. došlo je do degradacije performansi servera. Kao rezultat toga - degradacija performansi naše aplikacije. Pri tome je broj poziva ostao otprilike na istoj razini.

Uobičajene greške u aplikacijama koje dovode do bloat-a u PostgreSQL-u. Andrey Salkinov

Ovdje je važno razumjeti kako ispravno provoditi takve migracije. A one su neophodne. Ove migracije radimo prilično redovito.

  • Takve velike migracije se ne rade automatski. One uvijek moraju biti pod kontrolom.
  • Potrebna je kontrola od strane iskusne osobe. Ako imate DBA u timu, neka to radi DBA. To je njegov posao. Ako nemate, neka to učini najiskusnija osoba koja zna raditi s bazama podataka.
  • Nova shema baze podataka, čak i ako ažuriramo samo jedan stupac, uvijek se priprema u fazama, tj. unaprijed prije nego što se nova verzija aplikacije izvrši:
  • Dodaju se nova polja u koja ćemo zapisivati ažurirane podatke.
  • Prebacujemo podatke iz starog polja u novo polje u manjim dijelovima. Zašto to radimo? Prvo, uvijek kontroliramo proces ovog prebacivanja. Znamo da smo prenijeli određeni broj batch-eva i da nam još ostaje toliki.
  • A druga pozitivna stvar je to da između svakog takvog batch-a zatvaramo transakciju, otvaramo novu i to omogućava automatskom vakuumu da odradi svoj posao na tablici, označavajući mrtve redove za ponovnu upotrebu.
  • Za redove koji će se pojaviti tijekom rada aplikacije (starija aplikacija još uvijek radi) dodajemo okidač koji zapisuje nove vrijednosti u nova polja. U našem slučaju - to je množenje starog vrijednosti s sto.
  • Ako smo potpuno uporni i želimo isto to polje, onda, nakon završetka svih migracija i prije implementacije nove verzije aplikacije, jednostavno preimenujemo polja. Stara u neko izmišljeno ime, a nova polja preimenujemo u stara.
  • Tek nakon toga pokrećemo novu verziju aplikacije.

I pritom nećemo dobiti bloat i nećemo pogoršati performanse.

Ovdje se završila treća priča.

Uobičajene greške u aplikacijama koje dovode do bloat-a u PostgreSQL-u. Andrey Salkinov

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

Sada ću malo detaljnije objasniti alate koje sam spomenuo u prvoj priči.

Prije nego što počnete tražiti bloat, obavezno instalirajte proširenje. pgstattuple.

Da vam ne bih smišljao upite, već smo ih napisali u našoj praksi. Možete ih koristiti. Ovdje su predstavljena dva upita.

  • Prvi traje dosta dugo, ali će vam pokazati točne vrijednosti bloat-a po tablici.
  • Drugi radi brže i vrlo je učinkovit kada je potrebno brzo procijeniti — postoji li bloat ili ne po tablici. Također morate razumjeti da bloat u Postgres tablicama uvijek postoji. To je posebnost njegovog MVCC modela.
  • I 20% bloat-a je normalno za tablice u većini slučajeva. Dakle, ne trebate se previše brinuti i komprimirati ovu tablicu.

Kako identificirati tablice koje su nam se napuhale, razjasnili smo, pa čak i kada su se napuhale beskorisnim podacima.

Sada o tome kako ispraviti bloat:

  • Ako imamo malu tablicu i dobre diskove, to jest, ako je tablica manja od jednog gigabajta, moguće je koristiti VACUUM FULL. Uzeće ekskluzivnu blokadu na tablici na nekoliko sekundi, ali će sve učiniti brzo i efikasno. Što radi VACUUM FULL? Uzimaje ekskluzivnu blokadu na tablicu i iz starih tablica prepisuje aktivne redove u novu tablicu. Na kraju zamijeni stare i nove. Stare datoteke briše, nove postavlja umjesto starih. Ali tokom svog rada uzima ekskluzivnu blokadu tablice. To znači da s tom tablicom nećete moći raditi ništa: ne možete pisati, čitati ili modificirati je. Također, VACUUM FULL zahtijeva dodatni prostor na disku za zapis podataka.
  • Sljedeći alat pg_repack. Po svom principu je vrlo sličan VACUUM FULL, jer također prepisuje podatke iz starih datoteka u nove i zamjenjuje ih u tablici. Ali ne uzima ekskluzivnu blokadu na tablici na samom početku svog rada, već samo u trenutku kada već ima pripremljene podatke za zamjenu datoteka. Zahtjevi za diskovnim resursima su slični onima kod VACUUM FULL. Trebat će vam dodatni prostor na disku, a to ponekad može biti kritično, ako imate tablice od jednog terabajta. Također je prilično zahtjevan prema procesoru, jer aktivno radi s unosom i izlazom.
  • Treća alatka je pgcompacttable. Ponaša se štedljivije prema resursima jer radi na malo drugačijim principima. Suština pgcompacttable je u tome što ažuriranjem u tablici premješta sve aktivne redove na početak tablice. Zatim pokreće vakuum na toj tablici, jer znamo da su na početku aktivni, a na kraju neaktivni redovi. A vakuum već sam odrezuje taj rep, tj. ne zahtijeva previše dodatnog prostor. Također ga je još moguće optimizirati prema resursima.

Sa alatima je sve.

Uobičajene greške u aplikacijama koje dovode do bloat-a u PostgreSQL-u. Andrey Salkinov

Ako vam tema o bloat-u izgleda zanimljivo za dublje istraživanje, evo nekih korisnih linkova:

Pokušao sam ovdje više prikazati zastrašujuću sliku za developere, jer su oni naši neposredni klijenti baza podataka i trebaju razumjeti do koje mjere i kakve akcije vode. Nadam se da mi je to uspjelo. Hvala na pažnji!

Pitanja

Hvala za izlaganje! Govorili ste o tome kako mogu identificirati probleme. Kako ih mogu prevenirati? Imala sam situaciju kada su upiti visjeli ne samo zbog pozivanja nekih vanjskih servisa. Bili su to jednostavno neki divlji joins. Imali smo neke sitne neškodljive upite koji su visjeli danima, a zatim su počeli raditi neku glupost. Znači, jako slično onome što opisujete. Kako to pratiti? Treba li sjediti i stalno gledati koji upit je visio? Kako to prevenirati?

U ovom slučaju – to je zadatak za administratore vaše tvrtke, ne nužno za DBA.

Ja sam administrator.

U PostgreSQL postoji prikaz nazvan pg_stat_activity, koji prikazuje visjele upite. Tamo možete vidjeti koliko dugo su visjeli.

Treba li da svake 5 minuta provjeravam?

Postavite cron i provjerite. Ako imate dug zahtjev, pišite email i to je to. Odnosno, ne morate to gledati vlastitim očima, to se može automatizirati. Doći će vam e-mail, vi reagirate na njega. A možete i automatski ispaliti.

Postoje li očiti razlozi zašto se to događa?

Neke sam naveo. Drugi su složeniji primjeri. I tu bi razgovor mogao potrajati.

Hvala na prezentaciji! Htio sam pojasniti vezano uz alat pg_repack. Ako ne pravi ekskluzivnu blokadu, onda…

Ona pravi ekskluzivnu blokadu.

… onda potencijalno mogu izgubiti podatke. Moja aplikacija ne bi trebala ništa zapisivati u to vrijeme?

Ne, ona mirno radi s tablicom, tj. pg_repack prvo premješta sve aktivne redove koji postoje. Naravno, tamo se odvija neka vrsta zapisa u tablici. On jednostavno dodaje taj ostatak.

Odnosno, na kraju ipak to radi?

Na kraju uzima ekskluzivnu blokadu kako bi zamijenio ta mjesta između tih datoteka.

Hoće li to biti brže od VACUUM FULL?

VACUUM FULL, čim počne, odmah uzima ekskluzivnu blokadu. I sve dok ne završi, ne pušta je. A pg_repack uzima ekskluzivnu blokadu samo u trenutku zamjene datoteka. U tom trenutku ne možete zapisivati, ali podaci se neće izgubiti, sve će biti u redu.

Dobar dan! Govorili ste o radu automatskog vakuuma. Tamo je bio grafikon s crvenim, žutim i zelenim ćelijama zapisa. Odnosno, žute – on je označio kao obrisane. I kao posljedica može li se u njih zapisivati novo?

Da. Postgres ne briše redove. Ima tu specifičnost. Ako smo ažurirali red, stare označimo kao obrisane. Tada se postavlja ID transakcije koja je izmijenila taj red i zapisujemo novi red. I imamo sesije koje potencijalno mogu čitati te redove. U nekom trenutku oni postaju sasvim stari. A suština rada automatskog vakuuma je da prolazi kroz te redove i označava ih kao nepotrebne. I ondje se mogu prepisati podaci.

Razumijem. No pitanje nije baš to. Nisam završio. Pretpostavimo da imamo tablicu. U njoj su polja promjenjive veličine. I ako pokušam umetnuti nešto novo, tada to možda neće stati u staru ćeliju.

Ne, u svakom slučaju cijela linija se ažurira. U Postgresu postoje dva modela pohrane podataka. Određuje se prema vrsti podataka. Postoje podaci koji se pohranjuju izravno u tablicu, a tu su i tos-podaci. To su velike količine podataka: tekst, json. Oni se pohranjuju u posebnim tablicama. I sa tim tablicama događa se isto što i s bloat-om, tj. sve je isto. Samo su odvojeni.

Hvala na izlaganju! Koliko je prihvatljivo koristiti requests statement timeout za ograničavanje trajanja upita?

Vrlo je prihvatljivo. Mi to koristimo svugdje. A budući da nemamo vlastite usluge, pružamo udaljenu podršku, te imamo prilično raznolike klijente. Svi su posve zadovoljni. Tj. imamo zadatke u cron-u koji provjeravaju. Jednostavno se s klijentom dogovara trajanje sesija, ispod kojeg ne “ubijamo”. To može biti minuta, to može biti 10 minuta. Ovisi o opterećenju baze i njezinoj svrsi. Ali svi koristimo pg_stat_activity.

Hvala na izlaganju! Pokušavam prilagoditi vaše izlaganje svojim aplikacijama. I činilo mi se da svugdje započinjemo transakciju, svugdje je izričito završavamo. Ako dođe do bilo kakvog exception-a, rollback se ionako odvija. I onda sam se zamislio. Naime, transakcija se može pokrenuti neizravno. To je možda sugestija za djevojku. Ako jednostavno ažuriram zapis, transakcija će se pokrenuti u PostgreSQL-u i završit će tek kada dođe do prekida veze?

Ako sada govorite o razini aplikacije, to ovisi o onome što koristite, o tom ORM-u koji se koristi. Tu je jako puno postavki. Ako imate uključeno auto commit on, tada se transakcija pokreće i odmah zatvara.

Tj. zatvara se odmah nakon ažuriranja?

To ovisi o postavkama. Jednu postavku sam spomenuo. To je auto commit on. To je prilično rasprostranjeno. Ako je uključeno, transakcija se otvorila-zatvorila. Ako izričito ne kažete 'start transaction' i 'end transaction', nego jednostavno pokrenete upit u sesiji.

Dobar dan! Hvala na izlaganju! Pretpostavimo da imamo bazu koja se širi i na serveru nestaje prostora. Postoje li neki alati kako bi se to riješilo?

Prostor na serveru treba pratiti.

Na primjer, DBA je otišao na čaj, bio je na odmoru itd.

Kada se stvara datotečni sustav, minimálně se stvara neka rezervirana površina gdje se ne pohranjuju podaci.

A ako potpuno na nuli?

Tamo se to naziva rezervirani prostor, odnosno, može se osloboditi, a ovisno o tome koliko je velik stvoren, dobivate slobodan prostor. Po defaultu ne znam koliko tamo ima. A u drugom slučaju – dostaviti diskove da imate prostor za izvođenje postupka obnove. Možete obrisati neku tablicu koja vam sigurno nije potrebna.

Nema drugih alata?

To je uvijek ručni rad. I na licu mjesta se utvrđuje šta je bolje učiniti, jer postoje kritični podaci, postoje nekritični. I za svaku bazu i aplikaciju koja s njom radi, to ovisi o poslovanju. Uvijek se odlučuje na licu mjesta.

Hvala na prezentaciji! Imam dva pitanja. Prvo, demonstrirali ste slajdove na kojima je prikazano da, u slučaju zaključenih transakcija, raste i volumen tabličnog prostora i veličina indeksa. A zatim u prezentaciji je bilo mnogo alata koji pakiraju tablicu. A šta je sa indeksom?

Oni također pakiraju indekse.

Ali vakuum ne zahvaća indeks?

Neki rade s indeksom. Na primjer, pg_rapack, pgcompacttable. Vakuum ponovno stvara indekse, zahvaća ih. Suština VACUUM FULL je da sve prepisuje, t.j. radi sa svima.

I drugo pitanje. Nisam razumio zašto izvještaji na replikama tako jako ovise o samoj replikaciji. Mislio sam da su izvještaji – to je čitanje, a replikacija – to je pisanje.

U čemu se javlja konflikt replikacije? Imamo Master odakle se odvijaju procesi. Ovdje se odvija autovakuum. Autovakuum zapravo radi šta? Uklanja neke stare retke. Ako u ovom trenutku na replici ide upit koji čita te stare retke, a na Masteru se dogodila situacija gdje je autovakuum označio te retke kao mogućne za prepisivanje, onda ih prepisujemo. I dolazi nam paket podataka kada trebamo prepisati one retke koji su potrebni upitu na replici, proces replikacije će čekati onaj timeout koji ste postavili. A potom će PostgreSQL odlučiti što je važnije za njega. A replikacija je njemu važnija od upita i on će obustaviti upit da izvrši te promjene na replici.

Andrej, imam pitanje. Ove divne grafike koje ste prikazali tijekom prezentacije, jesu li to rezultati rada neke vaše alatke? Čime su graficirane grafike?

To je usluga Okmeter.

Je li to komercijalni proizvod?

Da. To je komercijalni proizvod.

Izvor: habr.com

Kupite pouzdan hosting za web stranice s DDoS zaštitom, VPS VDS servere 🔥 Kupite pouzdan hosting za web stranice s DDoS zaštitom, VPS VDS servere | ProHoster