Tipiškos programų klaidos, dėl kurių postgresql išpūstas. Andrejus Salnikovas

Siūlau perskaityti 2016 m. pradžios Andrejaus Salnikovo pranešimo „Tipinės programos klaidos, dėl kurių atsiranda postgresql išsipūtimas“ stenogramą.

Šioje ataskaitoje išanalizuosiu pagrindines programų klaidas, kurios atsiranda projektuojant ir rašant programos kodą. Ir aš imsiu tik tas klaidas, dėl kurių „Postgresql“ išsipūsti. Paprastai tai yra visos jūsų sistemos veikimo pabaigos pradžia, nors iš pradžių tam nebuvo jokių prielaidų.

Tipiškos programų klaidos, dėl kurių postgresql išpūstas. Andrejus Salnikovas

Malonu visus pasveikinti! Šis pranešimas nėra toks techninis, kaip ankstesnis mano kolegos pranešimas. Ši ataskaita daugiausia skirta backend sistemų kūrėjams, nes turime gana daug klientų. Ir visi jie daro tas pačias klaidas. Papasakosiu apie juos. Paaiškinsiu, prie kokių lemtingų ir blogų dalykų priveda šios klaidos.

Tipiškos programų klaidos, dėl kurių postgresql išpūstas. Andrejus Salnikovas

Kodėl daromos klaidos? Jie daromi dėl dviejų priežasčių: atsitiktinai, galbūt tai pasiteisins, ir dėl kai kurių mechanizmų, atsirandančių lygyje tarp duomenų bazės ir programos, taip pat pačioje duomenų bazėje, nežinojimo.

Pateiksiu tris pavyzdžius su siaubingomis nuotraukomis, kaip viskas pablogėjo. Trumpai papasakosiu apie ten vykstantį mechanizmą. Ir kaip su jomis elgtis, kada jos įvyko ir kokiais prevenciniais metodais apsisaugoti nuo klaidų. Papasakosiu apie pagalbinius įrankius ir pateiksiu naudingų nuorodų.

Tipiškos programų klaidos, dėl kurių postgresql išpūstas. Andrejus Salnikovas

Naudojau bandomąją duomenų bazę, kurioje turėjau dvi lenteles. Viena plokštelė su klientų sąskaitomis, kita – su šių sąskaitų operacijomis. Ir tam tikru dažnumu mes atnaujiname šių sąskaitų likučius.

Tipiškos programų klaidos, dėl kurių postgresql išpūstas. Andrejus Salnikovas

Pradiniai plokštelės duomenys: ji gana maža, 2 MB. Duomenų bazės ir konkrečiai ženklo reakcijos laikas taip pat labai geras. Ir gana geras krūvis – 2 operacijų per sekundę pagal plokštelę.

Tipiškos programų klaidos, dėl kurių postgresql išpūstas. Andrejus Salnikovas

Ir per šią ataskaitą aš parodysiu jums grafikus, kad galėtumėte aiškiai suprasti, kas vyksta. Visada bus 2 skaidrės su grafikais. Pirmoji skaidrė yra tai, kas apskritai vyksta serveryje.

Ir šioje situacijoje matome, kad tikrai turime mažą ženklą. Indeksas mažas – 2 MB. Tai pirmas grafikas kairėje.

Vidutinis atsako laikas serveryje taip pat yra stabilus ir trumpas. Tai yra viršutinis dešinysis grafikas.

Apatiniame kairiajame grafike rodomos ilgiausios operacijos. Matome, kad operacijos atliekamos greitai. O autovakuumas čia dar neveikia, nes tai buvo starto testas. Jis veiks ir toliau ir bus mums naudingas.

Tipiškos programų klaidos, dėl kurių postgresql išpūstas. Andrejus Salnikovas

Antroji skaidrė visada bus skirta bandomai plokštelei. Esant tokiai situacijai, nuolat atnaujiname kliento sąskaitų likučius. Ir matome, kad vidutinis atnaujinimo operacijos atsako laikas yra gana geras, mažiau nei milisekundė. Matome, kad procesoriaus ištekliai (tai yra viršutinis dešinysis grafikas) taip pat sunaudojami tolygiai ir gana mažai.

Apatinis dešinysis grafikas rodo, kiek operacinės ir disko atminties praleidžiame ieškodami norimos eilutės prieš ją atnaujindami. O operacijų skaičius pagal ženklą – 2 per sekundę, kaip sakiau pradžioje.

Tipiškos programų klaidos, dėl kurių postgresql išpūstas. Andrejus Salnikovas

O dabar mus ištiko tragedija. Kažkodėl yra seniai pamirštas sandoris. Priežastys paprastai yra banalios:

  • Vienas iš labiausiai paplitusių yra tai, kad mes pradėjome pasiekti išorinę paslaugą programos kode. Ir ši paslauga mums neatsako. Tai reiškia, kad atidarėme operaciją, pakeitėme duomenų bazę ir iš programos perėjome prie pašto skaitymo ar kitos infrastruktūros paslaugos ir dėl tam tikrų priežasčių ji mums neatsako. Ir mūsų sesija įstrigo tokioje būsenoje, kai nežinia, kada ji bus išspręsta.
  • Antra situacija, kai mūsų kode dėl kokios nors priežasties įvyko išimtis. Išimties atveju mes neapdorojome sandorio uždarymo. Ir baigėme pakabinimo seansą su atviru sandoriu.
  • Ir paskutinis – taip pat gana dažnas atvejis. Tai žemos kokybės kodas. Kai kurios sistemos atidaro sandorį. Jis kabo, o programoje galite nežinoti, kad jis kabo.

Kur tokie dalykai veda?

Tiek, kad mūsų lentelės ir indeksai pradeda smarkiai išsipūsti. Tai lygiai toks pat išsipūtimo efektas. Duomenų bazei tai reikš, kad labai smarkiai padidės duomenų bazės reakcijos laikas ir padidės duomenų bazės serverio apkrova. Dėl to mūsų programa nukentės. Nes jei praleidote 10 milisekundžių savo kode pateikdami užklausą duomenų bazei, 10 milisekundžių – savo logikai, tada jūsų funkcijai atlikti prireikė 20 milisekundžių. Ir dabar jūsų padėtis bus labai liūdna.

Ir pažiūrėkime, kas atsitiks. Apatiniame kairiajame grafike matyti, kad turime ilgą ir ilgą sandorį. O jei pažiūrėtume į viršutinį kairįjį grafiką, pamatytume, kad mūsų lentelės dydis staiga šoktelėjo nuo dviejų megabaitų iki 300 megabaitų. Tuo pačiu metu duomenų kiekis lentelėje nepasikeitė, t.y. ten yra gana daug šiukšlių.

Tipiškos programų klaidos, dėl kurių postgresql išpūstas. Andrejus Salnikovas

Bendra padėtis dėl vidutinio serverio atsako laiko taip pat pasikeitė keliomis eilėmis. Tai reiškia, kad visos užklausos serveryje pradėjo visiškai mažėti. O tuo pat metu autovakuumo pavidalu buvo paleisti vidiniai Postgres procesai, kurie bando kažką daryti ir eikvoja resursus.

Tipiškos programų klaidos, dėl kurių postgresql išpūstas. Andrejus Salnikovas

Kas vyksta su mūsų ženklu? Tas pats. Mūsų vidutinis reakcijos laikas pagal ženklą šoktelėjo keliais dydžiais. Konkrečiai kalbant apie sunaudotus resursus, matome, kad procesoriaus apkrova labai išaugo. Tai yra viršutinis dešinysis grafikas. Ir jis padidėjo, nes procesorius turi rūšiuoti daugybę nenaudingų eilučių, ieškodamas reikalingos. Tai yra apatinis dešinysis grafikas. Ir dėl to mūsų skambučių skaičius per sekundę pradėjo labai mažėti, nes duomenų bazė neturėjo laiko apdoroti tiek pat užklausų.

Tipiškos programų klaidos, dėl kurių postgresql išpūstas. Andrejus Salnikovas

Turime grįžti į gyvenimą. Prisijungiame prie interneto ir sužinome, kad dėl ilgų sandorių kyla problemų. Mes surandame ir nužudome šį sandorį. O pas mus viskas tampa įprasta. Viskas veikia kaip priklauso.

Nusiraminome, bet po kurio laiko pradedame pastebėti, kad programa neveikia taip, kaip prieš skubią situaciją. Užklausos vis tiek apdorojamos lėčiau ir žymiai lėčiau. Pusantro ar du kartus lėčiau konkrečiai mano pavyzdyje. Serverio apkrova taip pat didesnė nei buvo prieš avariją.

Tipiškos programų klaidos, dėl kurių postgresql išpūstas. Andrejus Salnikovas

Ir klausimas: „Kas šiuo metu vyksta su baze? O su baze atsitinka tokia situacija. Sandorių diagramoje matote, kad jis sustojo ir tikrai nėra ilgalaikių sandorių. Tačiau per avariją ženklo dydis mirtinai išaugo. Ir nuo to laiko jų nesumažėjo. Vidutinis laikas bazėje stabilizavosi. Ir atrodo, kad atsakymai ateina adekvačiai mums priimtinu greičiu. Autovakuumas suaktyvėjo ir pradėjo kažką daryti su ženklu, nes reikia atsijoti daugiau duomenų.

Tipiškos programų klaidos, dėl kurių postgresql išpūstas. Andrejus Salnikovas

Tiksliau, pagal bandomąją lentelę su sąskaitomis, kur keičiame likučius: panašu, kad atsakymo į užklausą laikas normalizavosi. Tačiau iš tikrųjų jis yra pusantro karto didesnis.

O iš procesoriaus apkrovos matome, kad procesoriaus apkrova negrįžo iki reikiamos vertės prieš gedimą. O priežastys slypi būtent apatiniame dešiniajame grafike. Matosi, kad ten ieškoma tam tikro atminties kiekio. Tai yra, norėdami rasti reikiamą eilutę, eikvojame duomenų bazės serverio išteklius rūšiuodami nenaudingus duomenis. Transakcijų skaičius per sekundę stabilizavosi.

Apskritai viskas gerai, bet situacija yra blogesnė nei buvo. Aiškus duomenų bazės pablogėjimas dėl mūsų programos, veikiančios su šia duomenų baze.

Tipiškos programų klaidos, dėl kurių postgresql išpūstas. Andrejus Salnikovas

Ir norėdami suprasti, kas ten vyksta, jei nebuvote ankstesniame pranešime, dabar pažvelkime į teoriją. Teorija apie vidinį procesą. Kodėl automobilio siurblys ir ką jis daro?

Pažodžiui trumpai, kad suprastum. Tam tikru metu mes turime stalą. Lentelėje turime eilutes. Šios linijos gali būti aktyvios, gyvos ir tai, ko mums reikia dabar. Nuotraukoje jie pažymėti žalia spalva. Ir yra eilučių, kurios jau buvo išdirbtos, atnaujintos ir jose atsirado naujų įrašų. Ir jie pažymėti, kad jie nebeįdomūs duomenų bazei. Tačiau jie yra lentelėje dėl „Postgres“ funkcijos.

Kodėl jums reikia automobilio dulkių siurblio? Tam tikru momentu automatinis vakuumas ateina, prisijungia prie duomenų bazės ir jos paprašo: „Duokite man seniausios operacijos, kuri šiuo metu yra atidaryta duomenų bazėje, ID. Duomenų bazė grąžina šį ID. O autovakuumas, juo pasikliaudamas, rūšiuoja lentelės eilutes. Ir jei mato, kad kai kurios eilutės buvo pakeistos daug senesnių sandorių, tai jis turi teisę pažymėti jas kaip eilutes, kurias galėsime panaudoti ateityje, įrašydami ten naujus duomenis. Tai yra foninis procesas.

Šiuo metu mes toliau dirbame su duomenų baze ir toliau atliekame kai kuriuos lentelės pakeitimus. Ir šiose eilutėse, kurias galime pakartotinai panaudoti, rašome naujus duomenis. Ir taip gauname ciklą, t.y. visą laiką ten atsiranda negyvų senų eilučių, vietoj jų užrašome naujas, kurių mums reikia. Ir tai yra normali PostgreSQL veikimo būsena.

Tipiškos programų klaidos, dėl kurių postgresql išpūstas. Andrejus Salnikovas

Kas atsitiko per avariją? Kaip ten vyko šis procesas?

Mes turėjome ženklą tam tikros būklės, kai kurie gyvi, kai kurios negyvos linijos. Atvažiavo automobilio siurblys. Jis paklausė duomenų bazės, kokia yra mūsų seniausia operacija ir koks jos ID. Gavau šį ID, kuris galėjo būti prieš daug valandų, gal prieš dešimt minučių. Tai priklauso nuo jūsų duomenų bazės apkrovos. Ir jis ieškojo eilučių, kurias galėtų pažymėti kaip pakartotinai panaudotas. Ir tokių eilučių mūsų lentelėje neradau.

Tačiau šiuo metu mes ir toliau dirbame su lentele. Kažką jame darome, atnaujiname, keičiame duomenis. Ką duomenų bazė turėtų daryti šiuo metu? Ji neturi kito pasirinkimo, kaip tik pridėti naujų eilučių esamos lentelės gale. Ir taip mūsų stalo dydis pradeda išsipūsti.

Iš tikrųjų mums reikia žalių linijų, kad veiktų. Tačiau tokios problemos metu paaiškėja, kad žalių linijų procentas yra labai mažas visoje lentelėje.

O kai vykdome užklausą, duomenų bazė turi pereiti visas eilutes: ir raudoną, ir žalią, kad rastų norimą eilutę. O lentelės išpūtimas nenaudingais duomenimis vadinamas „išpūtimu“, kuris taip pat suvalgo vietos diske. Prisimeni, tai buvo 2 MB, tapo 300 MB? Dabar pakeiskite megabaitus į gigabaitus ir greitai prarasite visus disko išteklius.

Tipiškos programų klaidos, dėl kurių postgresql išpūstas. Andrejus Salnikovas

Kokios gali būti pasekmės mums?

  • Mano pavyzdyje lentelė ir indeksas išaugo 150 kartų. Kai kurie mūsų klientai turėjo ir daugiau mirtinų atvejų, kai jiems tiesiog pradėjo trūkti vietos diske.
  • Pačių lentelių dydis niekada nesumažės. Autovakuumas kai kuriais atvejais gali nupjauti stalo uodegą, jei yra tik nejudančios linijos. Bet kadangi yra nuolatinis sukimasis, viena žalia eilutė gali sustingti pabaigoje ir būti neatnaujinta, o visos kitos bus užrašytos kažkur plokštelės pradžioje. Tačiau tai yra toks mažai tikėtinas įvykis, kad jūsų stalas sumažės, todėl neturėtumėte to tikėtis.
  • Duomenų bazėje reikia surūšiuoti daugybę nenaudingų eilučių. Ir mes eikvojame disko resursus, eikvojame procesoriaus resursus ir elektrą.
  • Ir tai tiesiogiai veikia mūsų programą, nes jei pradžioje užklausai skyrėme 10 milisekundžių, kodui – 10 milisekundžių, tai gedimo metu pradėjome skirti sekundę užklausai ir 10 milisekundžių kodui, t.y. sumažėjo programos našumas. Ir kai avarija buvo išspręsta, pradėjome praleisti 20 milisekundžių prašymui, 10 milisekundžių kodui. Tai reiškia, kad produktyvumas vis tiek sumažėjo pusantro karto. Ir visa tai dėl vieno sandorio, kuris įšaldytas, galbūt dėl ​​mūsų kaltės.
  • Ir klausimas: „Kaip viską susigrąžinti?“, kad pas mus viskas būtų gerai ir prašymai ateitų taip pat greitai, kaip ir prieš avariją.

Tipiškos programų klaidos, dėl kurių postgresql išpūstas. Andrejus Salnikovas

Šiuo tikslu atliekamas tam tikras darbų ciklas.

Pirmiausia turime rasti problemines lenteles, kurios yra išpūstos. Suprantame, kad vienose lentelėse įrašymas aktyvesnis, kitose – mažiau. Ir tam mes naudojame plėtinį pgstattuple. Įdiegę šį plėtinį galite rašyti užklausas, kurios padės rasti gana išpūstas lenteles.

Suradę šias lenteles, turite jas suspausti. Tam jau yra įrankių. Mūsų įmonėje naudojame tris įrankius. Pirmasis yra įmontuotas VACUUM FULL. Jis žiaurus, atšiaurus ir negailestingas, bet kartais labai naudingas. Pg_repack и pgkompaktiškas - Tai yra trečiųjų šalių paslaugų, skirtų lentelėms suspausti. Ir jie atidžiau elgiasi su duomenų baze.

Jie naudojami priklausomai nuo to, kas jums patogiau. Bet aš jums apie tai papasakosiu pačioje pabaigoje. Svarbiausia, kad yra trys įrankiai. Yra iš ko rinktis.

Viską ištaisę ir įsitikinę, kad viskas gerai, turime žinoti, kaip išvengti tokios situacijos ateityje:

  • To galima gana lengvai išvengti. Turite stebėti seansų trukmę pagrindiniame serveryje. Ypač pavojingi seansai neveikiant operacijos būsenoje. Tai tie, kurie ką tik atidarė operaciją, kažką padarė ir išėjo arba tiesiog pakibo, pasiklydo kode.
  • Ir jums, kaip kūrėjams, svarbu išbandyti savo kodą, kai atsiranda tokių situacijų. Tai padaryti nesunku. Tai bus naudingas patikrinimas. Išvengsite daugybės „vaikiškų“ problemų, susijusių su ilgais sandoriais.

Tipiškos programų klaidos, dėl kurių postgresql išpūstas. Andrejus Salnikovas

Šiuose grafikuose norėjau parodyti, kaip pasikeitė ženklas ir duomenų bazės elgsena, kai šiuo atveju perėjau ženklą su VACUUM FULL. Man tai ne gamyba.

Lentelės dydis iš karto grįžo į įprastą poros megabaitų veikimo būseną. Tai neturėjo didelės įtakos vidutiniam serverio atsako laikui.

Tipiškos programų klaidos, dėl kurių postgresql išpūstas. Andrejus Salnikovas

Bet konkrečiai mūsų bandomajam ženklui, kuriame atnaujinome sąskaitų likučius, matome, kad vidutinis atsakymo laikas į užklausą atnaujinti ženkle esančius duomenis buvo sumažintas iki lygio, buvusio prieš avarinę situaciją. Ištekliai, kuriuos procesorius sunaudojo šiai užklausai įvykdyti, taip pat sumažėjo iki lygio, buvusio prieš strigtį. Ir apatiniame dešiniajame grafike matyti, kad dabar mes iš karto randame būtent tą eilutę, kurios mums reikia, neperžengdami negyvų eilučių krūvų, kurios buvo prieš suspaudžiant lentelę. O vidutinis užklausų pateikimo laikas išliko maždaug toks pat. Bet čia veikiau turiu aparatinės įrangos klaidą.

Tipiškos programų klaidos, dėl kurių postgresql išpūstas. Andrejus Salnikovas

Čia ir baigiasi pirmoji istorija. Tai yra labiausiai paplitęs. Ir taip nutinka visiems, nepriklausomai nuo kliento patirties ir programuotojų kvalifikacijos. Anksčiau ar vėliau tai įvyksta.

Antroji istorija, kurioje paskirstome apkrovą ir optimizuojame serverio resursus

Tipiškos programų klaidos, dėl kurių postgresql išpūstas. Andrejus Salnikovas

  • Mes jau užaugome ir tapome rimtais vaikinais. Ir suprantame, kad turime repliką ir mums būtų gerai subalansuoti krūvį: rašyti Meistrui, ir skaityti iš replikos. Ir dažniausiai tokia situacija susidaro tada, kai norime parengti kokias nors ataskaitas ar ETL. Ir verslas tuo labai džiaugiasi. Jis tikrai nori įvairių ataskaitų su daug sudėtingos analizės.
  • Ataskaitos užtrunka daug valandų, nes sudėtingos analizės negalima apskaičiuoti milisekundėmis. Mes, kaip drąsūs vaikinai, rašome kodą. Įterpimo programoje įrašome pagrindinį įrenginį ir vykdome kopijas.
  • Krovinio paskirstymas.
  • Viskas veikia puikiai. Mes puikūs.

Tipiškos programų klaidos, dėl kurių postgresql išpūstas. Andrejus Salnikovas

Ir kaip atrodo ši situacija? Konkrečiai šiose diagramose prie operacijos trukmės taip pat pridėjau operacijų trukmę iš replikos. Visi kiti grafikai nurodo tik pagrindinį serverį.

Iki to laiko mano ataskaitų lenta išaugo. Jų yra ir daugiau. Matome, kad vidutinis serverio atsako laikas yra stabilus. Matome, kad kopijoje turime ilgalaikę operaciją, kuri trunka 2 valandas. Matome tylų autovakuumo, kuris apdoroja negyvas linijas, veikimą. O pas mus viskas gerai.

Tipiškos programų klaidos, dėl kurių postgresql išpūstas. Andrejus Salnikovas

Tiksliau, pagal patikrintą plokštelę ten ir toliau atnaujiname sąskaitų likučius. Taip pat turime stabilų reagavimo į užklausas laiką, stabilų išteklių suvartojimą. Pas mus viskas gerai.

Tipiškos programų klaidos, dėl kurių postgresql išpūstas. Andrejus Salnikovas

Viskas gerai iki to momento, kai šios ataskaitos pradeda veikti dėl prieštaravimų su replikacija. Ir jie šaudo reguliariais intervalais.

Prisijungiame prie interneto ir pradedame skaityti, kodėl taip nutinka. Ir mes randame sprendimą.

Pirmasis sprendimas yra padidinti replikacijos delsą. Žinome, kad mūsų ataskaita trunka 3 valandas. Nustatome replikacijos delsą iki 3 valandų. Viską pradedame, bet vis tiek kyla problemų dėl kartais atšaukiamų ataskaitų.

Mes norime, kad viskas būtų tobula. Lipame toliau. Ir internete radome šaunų nustatymą – hot_standby_feedback. Įjunkime. „Hot_standby_feedback“ leidžia mums sulaikyti „Master“ automatinį vakuumą. Taigi mes visiškai atsikratome replikacijos konfliktų. O su ataskaitomis mums viskas gerai.

Tipiškos programų klaidos, dėl kurių postgresql išpūstas. Andrejus Salnikovas

O kas šiuo metu vyksta su pagrindiniu serveriu? Ir mes turime visišką bėdą dėl pagrindinio serverio. Dabar matome diagramas, kai įgalinau abu šiuos nustatymus. Ir matome, kad mūsų kopijos seansas kažkaip pradėjo daryti įtaką pagrindinio serverio situacijai. Ji turi poveikį, nes pristabdė automatinį vakuumą, kuris pašalina negyvas linijas. Mūsų stalo dydis vėl smarkiai išaugo. Vidutinis užklausos vykdymo laikas visoje duomenų bazėje taip pat smarkiai išaugo. Autovakuumai šiek tiek sugriežtėjo.

Tipiškos programų klaidos, dėl kurių postgresql išpūstas. Andrejus Salnikovas

Tiksliau, iš mūsų plokštelės matome, kad duomenų atnaujinimas joje taip pat šoktelėjo į dangų. CPU suvartojimas taip pat labai išaugo. Mes vėl išgyvename daugybę negyvų, nenaudingų linijų. Ir šio ženklo reakcijos laikas bei operacijų skaičius sumažėjo.

Tipiškos programų klaidos, dėl kurių postgresql išpūstas. Andrejus Salnikovas

Kaip tai atrodys, jei nežinosime, apie ką aš kalbėjau anksčiau?

  • Pradedame ieškoti problemų. Jei susidūrėme su problemomis pirmoje dalyje, žinome, kad tai gali būti dėl ilgo sandorio ir eikite į meistrą. Turime problemų dėl meistro. Dešrelės jam. Jis įkaista, jo apkrovos vidurkis yra apie šimtą.
  • Užklausos ten vyksta lėtai, bet nematome jokių ilgalaikių operacijų. Ir mes nesuprantame, kas yra. Mes nesuprantame, kur ieškoti.
  • Tikriname serverio įrangą. Galbūt mūsų reidas sudužo. Galbūt perdegė mūsų atminties kortelė. Taip, visko gali nutikti. Bet ne, serveriai nauji, viskas veikia gerai.
  • Visi veikia: administratoriai, kūrėjai ir direktorius. Niekas nepadeda.
  • Ir kažkuriuo momentu viskas staiga pradeda taisytis.

Tipiškos programų klaidos, dėl kurių postgresql išpūstas. Andrejus Salnikovas

Šiuo metu užklausa dėl mūsų kopijos buvo apdorota ir palikta. Gavome ataskaitą. Verslas vis dar laimingas. Kaip matote, mūsų ženklas vėl išaugo ir nesiruošia mažėti. Diagramoje su seansais palikau dalį šios ilgos operacijos iš kopijos, kad galėtumėte įvertinti, kiek užtruks, kol padėtis stabilizuosis.

Sesija baigta. Ir tik po kurio laiko serveris daugmaž susitvarko. Ir vidutinis atsakymo į užklausas laikas pagrindiniame serveryje grįžta į normalų. Nes pagaliau autovakuumas turi galimybę išvalyti ir pažymėti šias pasibaigusias linijas. Ir jis pradėjo dirbti savo darbą. Ir kaip greitai jis tai padaro, taip greitai susitvarkysime.

Tipiškos programų klaidos, dėl kurių postgresql išpūstas. Andrejus Salnikovas

Pagal išbandytą planšetę, kurioje atnaujiname sąskaitų likučius, matome lygiai tą patį vaizdą. Vidutinis paskyros atnaujinimo laikas taip pat palaipsniui normalizuojasi. Taip pat sumažėja procesoriaus suvartojami ištekliai. Ir operacijų skaičius per sekundę grįžta į normalų. Bet vėl grįžtame į normalų gyvenimą, ne tokie, kokie buvome prieš avariją.

Tipiškos programų klaidos, dėl kurių postgresql išpūstas. Andrejus Salnikovas

Bet kokiu atveju gauname našumo sumažinimą, kaip ir pirmuoju atveju, pusantro ar du kartus, o kartais ir daugiau.

Atrodo, kad viską padarėme teisingai. Paskirstykite krovinį. Įranga neveikia tuščiąja eiga. Prašymus suskirstėme pagal protą, bet vis tiek viskas pasirodė neblogai.

  • Neįjungti hot_standby_feedback? Taip, nerekomenduojama jo įjungti be ypač rimtų priežasčių. Nes šis posūkis tiesiogiai paveikia Master serverį ir sustabdo ten esančio autovakuumo veikimą. Įjungę ją kai kuriose kopijose ir pamiršę apie tai, galite nužudyti meistrą ir gauti didelių problemų su programa.
  • Padidinti max_standby_streaming_delay? Taip, ataskaitoms tai tiesa. Jei turite trijų valandų ataskaitą ir nenorite, kad ji užstrigtų dėl replikacijos konfliktų, tiesiog padidinkite delsą. Ilgalaikei ataskaitai niekada nereikia duomenų, kurie šiuo metu buvo patekę į duomenų bazę. Jei turite jį tris valandas, vadinasi, naudojate tam tikrą senų duomenų laikotarpį. Ir jums nebus jokio skirtumo, ar vėluoja tris valandas, ar šešias valandas, tačiau ataskaitas gausite nuosekliai ir neturėsite problemų dėl jų nukritimo.
  • Žinoma, turite valdyti ilgas kopijų seansus, ypač jei nuspręsite kopijoje įjungti hot_standby_feedback. Nes visko gali nutikti. Perdavėme šią kopiją kūrėjui, kad jis galėtų išbandyti užklausas. Jis parašė beprotišką prašymą. Jis paleido jį ir nuėjo gerti arbatos, o mes gavome įsteigtą Mokytoją. O gal įdėjome netinkamą programą. Situacijų būna įvairių. Kopijų seansai turi būti stebimi taip pat atidžiai, kaip ir pagrindiniame kompiuteryje.
  • Ir jei turite greitų ir ilgų užklausų dėl kopijų, tokiu atveju geriau jas padalinti, kad paskirstytumėte apkrovą. Tai nuoroda į streaming_delay. Jei norite greitai, turėkite vieną kopiją su nedideliu replikacijos uždelsimu. Jei norite teikti ilgalaikes ataskaitų užklausas, turėkite kopiją, kuri gali vėluoti 6 valandas arba dieną. Tai visiškai normali situacija.

Pasekmes pašaliname taip pat:

  • Randame išpūstus stalus.
  • O suspaudžiame patogiausiu mums tinkančiu įrankiu.

Antroji istorija čia baigiasi. Pereikime prie trečios istorijos.

Tipiškos programų klaidos, dėl kurių postgresql išpūstas. Andrejus Salnikovas

Taip pat gana įprasta mums, kai vykdome migraciją.

Tipiškos programų klaidos, dėl kurių postgresql išpūstas. Andrejus Salnikovas

  • Bet koks programinės įrangos produktas auga. Jai keliami reikalavimai keičiasi. Bet kokiu atveju mes norime tobulėti. Taip atsitinka, kad mums reikia atnaujinti lentelės duomenis, ty paleisti naujinimą dėl naujos funkcijos, kurią pristatome kaip savo kūrimo dalį, perkėlimą.
  • Senas duomenų formatas netenkina. Tarkime, dabar pereiname prie antrosios lentelės, kurioje turiu operacijas šiose sąskaitose. Ir tarkime, kad jie buvo rubliais, o mes nusprendėme padidinti tikslumą ir tai padaryti kapeikomis. Ir tam turime atlikti atnaujinimą: padauginkite lauką su operacijos suma iš šimto.
  • Šiuolaikiniame pasaulyje naudojame automatizuotus duomenų bazės versijų valdymo įrankius. Tarkim Liquibase. Ten registruojame savo migraciją. Mes tai išbandome savo bandymų bazėje. Viskas gerai. Atnaujinimas vyksta. Kurį laiką blokuoja darbą, bet gauname atnaujintus duomenis. Ir mes galime paleisti naujas funkcijas. Viskas buvo patikrinta ir patikrinta. Viskas pasitvirtino.
  • Vykdėme planinius darbus ir vykdėme migraciją.

Tipiškos programų klaidos, dėl kurių postgresql išpūstas. Andrejus Salnikovas

Štai perkėlimas su atnaujinimu, kuris pateikiamas prieš jus. Kadangi tai yra mano sąskaitos operacijos, plokštelė buvo 15 GB. O kadangi mes atnaujiname kiekvieną eilutę, tai su atnaujinimu padidinome lentelės dydį dvigubai, nes kiekvieną eilutę perrašėme.

Tipiškos programų klaidos, dėl kurių postgresql išpūstas. Andrejus Salnikovas

Perkėlimo metu su šia plokštele nieko negalėjome padaryti, nes visos užklausos jai buvo eilėje ir laukiama, kol šis atnaujinimas bus baigtas. Bet čia noriu atkreipti jūsų dėmesį į skaičius, esančius vertikalioje ašyje. Tai reiškia, kad vidutinis užklausos laikas iki migracijos yra apie 5 milisekundės ir procesoriaus apkrova, disko atminties skaitymo blokų operacijų skaičius yra mažesnis nei 7,5.

Tipiškos programų klaidos, dėl kurių postgresql išpūstas. Andrejus Salnikovas

Atlikome perkėlimą ir vėl kilo problemų.

Perkėlimas buvo sėkmingas, bet:

  • Senoji funkcija dabar užtrunka ilgiau.
  • Stalas vėl išaugo.
  • Serverio apkrova vėl tapo didesnė nei anksčiau.
  • Ir, žinoma, vis dar dirbame su gerai veikiančiu funkcionalumu, šiek tiek jį patobulinome.

Ir tai vėl yra išsipūtimas, kuris vėl sugadina mūsų gyvenimus.

Tipiškos programų klaidos, dėl kurių postgresql išpūstas. Andrejus Salnikovas

Čia parodysiu, kad lentelė, kaip ir ankstesni du atvejai, negrįš į ankstesnių dydžių. Atrodo, kad vidutinė serverio apkrova yra pakankama.

Tipiškos programų klaidos, dėl kurių postgresql išpūstas. Andrejus Salnikovas

O jei atsiversime lentelę su sąskaitomis, pamatysime, kad vidutinis užklausų laikas šiai lentelei padvigubėjo. Procesoriaus apkrova ir atmintyje surūšiuotų eilučių skaičius šoktelėjo virš 7,5, bet buvo mažesnis. O procesorių atveju šoktelėjo 2 kartus, blokinių operacijų atveju 1,5 karto, t.y. gavome serverio našumo pablogėjimą. Ir dėl to pablogėja mūsų programos veikimas. Tuo pačiu metu skambučių skaičius išliko maždaug toks pat.

Tipiškos programų klaidos, dėl kurių postgresql išpūstas. Andrejus Salnikovas

Ir čia svarbiausia suprasti, kaip teisingai atlikti tokias migracijas. Ir juos reikia padaryti. Šias migracijas atliekame gana nuosekliai.

  • Tokios didelės migracijos nevyksta automatiškai. Jie visada turi būti kontroliuojami.
  • Reikalinga išmanančio žmogaus priežiūra. Jei jūsų komandoje yra DBA, leiskite tai padaryti DBA. Tai jo darbas. Jei ne, tegul tai daro labiausiai patyręs žmogus, kuris moka dirbti su duomenų bazėmis.
  • Naują duomenų bazės schemą, net jei atnaujiname vieną stulpelį, visada ruošiame etapais, t. y. iš anksto prieš išleidžiant naują programos versiją:
  • Pridedami nauji laukai, kuriuose įrašysime atnaujintus duomenis.
  • Duomenis iš seno lauko į naują perkeliame nedidelėmis dalimis. Kodėl mes tai darome? Pirma, mes visada kontroliuojame šio proceso procesą. Žinome, kad jau tiek daug partijų perdavėme ir tiek daug liko.
  • Ir antras teigiamas efektas yra tas, kad tarp kiekvienos tokios partijos uždarome sandorį, atidarome naują ir tai leidžia autovakuumui dirbti pagal plokštę, pažymėti terminus pakartotiniam naudojimui.
  • Eilutėms, kurios pasirodys, kai programa veikia (vis dar veikia senoji programa), pridedame trigerį, kuris įrašo naujas reikšmes į naujus laukus. Mūsų atveju tai yra senosios vertės padauginimas iš šimto.
  • Jei esame visiškai užsispyrę ir norime to paties lauko, tada užbaigę visus perkėlimus ir prieš išleisdami naują programos versiją, laukus tiesiog pervardijame. Seniesiems suteikiamas koks nors sugalvotas pavadinimas, o naujieji laukai pervadinami į senuosius.
  • Ir tik po to paleidžiame naują programos versiją.

Ir tuo pačiu mes nesipūsime ir nenukentėsime dėl našumo.

Štai čia ir baigiasi trečioji istorija.

Tipiškos programų klaidos, dėl kurių postgresql išpūstas. Andrejus Salnikovas

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

O dabar šiek tiek plačiau apie priemones, kurias paminėjau pačioje pirmoje istorijoje.

Prieš ieškodami išsipūtimo, turite įdiegti plėtinį pgstattuple.

Kad jums nereikėtų kelti klausimų, mes jau esame parašę šias užklausas savo darbe. Galite juos naudoti. Čia yra du prašymai.

  • Pirmasis veiks gana ilgai, tačiau jis parodys tikslias išsipūtimo vertes iš lentelės.
  • Antrasis veikia greičiau ir labai efektyvus, kai pagal lentelę reikia greitai įvertinti, ar yra pilvo pūtimas, ar ne. Taip pat turėtumėte suprasti, kad „Postgres“ lentelėje visada yra išsipūtimas. Tai yra jo MVCC modelio savybė.
  • O 20% pilvo pūtimas daugeliu atvejų yra normalus stalams. Tai yra, neturėtumėte jaudintis ir suspausti šią lentelę.

Supratome, kaip atpažinti lenteles, kurios išpūstos nenaudingais duomenimis.

Dabar apie tai, kaip ištaisyti pilvo pūtimą:

  • Jei turime nedidelę planšetę ir gerus diskus, tai yra iki gigabaito planšetėje, tai visiškai įmanoma naudoti VACUUM FULL. Jis kelioms sekundėms paims iš jūsų ant stalo išskirtinę spyną ir gerai, bet viską padarys greitai ir griežtai. Ką veikia VACUUM FULL? Tai užfiksuoja išskirtinį užraktą ant stalo ir perrašo gyvas eilutes iš senų lentelių į naują lentelę. Ir pabaigoje jis juos pakeičia. Jis ištrina senus failus ir pakeičia senus naujais. Tačiau visą savo darbo laiką jis turi išskirtinį užraktą ant stalo. Tai reiškia, kad su šia lentele nieko negalite daryti: nei rašyti, nei skaityti, nei keisti. O VACUUM FULL reikalauja papildomos vietos diske duomenims įrašyti.
  • Kitas įrankis pg_repack. Savo principu jis labai panašus į VACUUM FULL, nes taip pat perrašo duomenis iš senų failų į naujus ir pakeičia juos lentelėje. Tačiau tuo pačiu metu jis neužima išskirtinio užrakto ant stalo pačioje savo darbo pradžioje, o tik tuo metu, kai jau turi paruoštus duomenis, kad galėtų pakeisti failus. Jo disko išteklių reikalavimai yra panašūs į VACUUM FULL reikalavimus. Jums reikia papildomos vietos diske, o tai kartais labai svarbu, jei turite terabaitų lenteles. Ir jis yra gana alkanas procesorių, nes aktyviai dirba su I/O.
  • Trečias naudingumas yra pgkompaktiškas. Ji yra atsargesnė su ištekliais, nes veikia pagal šiek tiek kitokius principus. Pagrindinė pgcompacttable idėja yra ta, kad naudojant lentelės naujinimus visos tiesioginės eilutės perkeliamos į lentelės pradžią. Ir tada šioje lentelėje veikia vakuumas, nes žinome, kad pradžioje turime gyvas eilutes, o pabaigoje – neveikiančias eilutes. Ir pats vakuumas šią uodegą nupjauna, t.y. nereikalauja daug papildomos vietos diske. Ir tuo pačiu metu jis vis dar gali būti suspaustas išteklių atžvilgiu.

Viskas su įrankiais.

Tipiškos programų klaidos, dėl kurių postgresql išpūstas. Andrejus Salnikovas

Jei jums atrodo, kad išsipūtimo tema yra įdomi gilinantis į vidų, čia yra keletas naudingų nuorodų:

Labiau stengiausi parodyti siaubo istoriją kūrėjams, nes jie yra mūsų tiesioginiai duomenų bazių klientai ir turi suprasti, prie ko ir kokių veiksmų priveda. Tikiuosi man pavyko. Ačiū už dėmesį!

Klausimai

Ačiū už pranešimą! Kalbėjote apie tai, kaip galite nustatyti problemas. Kaip juos galima įspėti? Tai yra, aš turėjau situaciją, kai užklausos užkliuvo ne tik dėl to, kad jie pasiekė kai kurias išorines paslaugas. Tai buvo tik keletas laukinių sujungimų. Buvo keletas mažų, nekenksmingų prašymų, kurie truko dieną, o tada pradėjo daryti nesąmones. Tai yra, labai panašu į tai, ką aprašei. Kaip tai sekti? Sėdi ir nuolat žiūri, kuris prašymas užstringa? Kaip galima to išvengti?

Šiuo atveju tai yra jūsų įmonės administratorių, nebūtinai DBA, užduotis.

Aš esu administratorė.

„PostgreSQL“ turi rodinį, vadinamą pg_stat_activity, kuriame rodomos kabančios užklausos. Ir matai, kiek laiko jis ten kabo.

Ar turiu ateiti ir žiūrėti kas 5 minutes?

Nustatykite cron ir patikrinkite. Jei turite ilgalaikį prašymą, parašykite laišką ir viskas. Tai yra, jums nereikia žiūrėti akimis, tai gali būti automatizuota. Gausite laišką, į jį reaguosite. Arba galite fotografuoti automatiškai.

Ar yra kokių nors akivaizdžių priežasčių, kodėl taip nutinka?

Kai kuriuos išvardijau. Kiti sudėtingesni pavyzdžiai. Ir pokalbis gali trukti ilgai.

Ačiū už pranešimą! Norėjau paaiškinti apie pg_repack įrankį. Jei ji nedaro išskirtinio užrakto, tada...

Ji daro išskirtinę užraktą.

... tada galiu prarasti duomenis. Ar mano programa neturėtų nieko įrašyti per šį laiką?

Ne, ji veikia sklandžiai su lentele, ty pg_repack pirmiausia perkelia visas egzistuojančias tiesiogines eilutes. Natūralu, kad ten įvyksta kažkoks įėjimas į lentelę. Jis tik išmeta šitą kuodą.

Tai yra, jis iš tikrųjų tai daro galų gale?

Galų gale jis naudojasi išskirtiniu užraktu, kad pakeistų šiuos failus.

Ar jis bus greitesnis nei VACUUM FULL?

VACUUM FULL, vos prasidėjęs iškart paėmė išskirtinę spyną. Ir kol jis visko nepadarys, tol jos nepaleis. Ir pg_repack įgauna išskirtinį užraktą tik failo pakeitimo metu. Šiuo metu jūs ten nerašysite, bet duomenys nebus prarasti, viskas bus gerai.

Sveiki! Kalbėjote apie automobilio dulkių siurblio veikimą. Buvo grafikas su raudonomis, geltonomis ir žaliomis įrašymo ląstelėmis. Tai yra geltonos – pažymėjo kaip ištrintas. Ir dėl to į juos galima įrašyti ką nors naujo?

Taip. Postgres neištrina eilučių. Jis turi tokią specifiką. Jei atnaujinome eilutę, senąją pažymėjome kaip ištrintą. Ten pasirodo operacijos, kuri pakeitė šią eilutę, ID, ir mes rašome naują eilutę. Ir mes turime sesijų, kurios galėtų juos perskaityti. Tam tikru momentu jie tampa gana seni. O autovakuumo veikimo esmė yra ta, kad jis eina per šias linijas ir pažymi jas kaip nereikalingas. Ir ten galite perrašyti duomenis.

Aš suprantu. Bet klausimas ne apie tai. Aš nebaigiau. Tarkime, kad turime lentelę. Jame yra įvairaus dydžio laukai. Ir jei bandysiu įterpti ką nors naujo, tai gali tiesiog netilpti į seną langelį.

Ne, bet kuriuo atveju ten atnaujinama visa eilutė. „Postgres“ turi du duomenų saugojimo modelius. Jis pasirenka iš duomenų tipo. Yra duomenų, kurie saugomi tiesiogiai lentelėje, taip pat yra tos duomenų. Tai dideli duomenų kiekiai: tekstas, json. Jie laikomi atskirose plokštelėse. Ir pagal šias tabletes atsiranda ta pati istorija su pilvo pūtimu, t.y. viskas yra taip pat. Jie tiesiog išvardyti atskirai.

Ačiū už pranešimą! Ar priimtina naudoti pareiškimo skirtojo laiko užklausas norint apriboti trukmę?

Labai priimtina. Mes tai naudojame visur. O kadangi mes neturime savo paslaugų, teikiame nuotolinę pagalbą, turime gana įvairių klientų. Ir visi tuo visiškai patenkinti. Tai yra, mes turime cron darbus, kurie tikrina. Užsiėmimų trukmė tiesiog derinama su klientu, prieš kurią nesusitariame. Tai gali būti minutę, tai gali būti 10 minučių. Tai priklauso nuo pagrindo apkrovos ir jos paskirties. Bet mes visi naudojame pg_stat_activity.

Ačiū už pranešimą! Bandau pritaikyti jūsų ataskaitą savo paraiškoms. Ir atrodo, kad sandorį pradedame visur ir aiškiai jį užbaigiame visur. Jei yra kokia nors išimtis, atšaukimas vis tiek vyksta. Ir tada aš pradėjau galvoti. Juk sandoris negali prasidėti aiškiai. Tai tikriausiai yra užuomina merginai. Jei tik atnaujinsiu įrašą, ar operacija prasidės PostgreSQL ir bus baigta tik atjungus ryšį?

Jei dabar kalbate apie programos lygį, tai priklauso nuo naudojamos tvarkyklės, nuo naudojamo ORM. Ten yra daug nustatymų. Jei įjungėte automatinį įsipareigojimą, operacija prasideda ten ir iškart uždaroma.

Tai yra, jis uždaromas iškart po atnaujinimo?

Tai priklauso nuo nustatymų. Pavadinau vieną nustatymą. Tai yra automatinis įsipareigojimas. Tai gana įprasta. Jei jis įjungtas, operacija atidaryta ir uždaryta. Nebent aiškiai pasakėte „pradėti operaciją“ ir „baigti operaciją“, o tiesiog paleidote užklausą seansui.

Sveiki! Ačiū už pranešimą! Įsivaizduokime, kad turime duomenų bazę, kuri plečiasi ir plečiasi, o tada serverio vieta baigiasi. Ar yra kokių nors priemonių šiai situacijai išspręsti?

Vieta serveryje turi būti tinkamai stebima.

Pavyzdžiui, DBA ėjo arbatos, buvo kurorte ir pan.

Sukūrus failų sistemą, sukuriama bent kažkokia atsarginė erdvė, kurioje duomenys nerašomi.

Ką daryti, jei jis yra visiškai žemiau nulio?

Ten ji vadinama rezervuota erdve, t.y., ją galima atlaisvinti ir priklausomai nuo to, kokio dydžio ji buvo sukurta, gausite laisvos vietos. Pagal numatytuosius nustatymus aš nežinau, kiek jų yra. O kitu atveju pristatykite diskus, kad turėtumėte vietos atlikti rekonstrukcinę operaciją. Galite ištrinti kokią nors lentelę, kurios jums garantuotai neprireiks.

Ar yra kitų priemonių?

Tai visada rankų darbo. Ir lokaliai tampa aišku, ką ten geriausia daryti, nes kai kurie duomenys yra kritiški, o kai kurie nekritiški. Kiekvienos duomenų bazės ir su ja veikiančios programos atveju tai priklauso nuo verslo. Visada sprendžiama vietoje.

Ačiū už pranešimą! Turiu du klausimus. Pirmiausia parodėte skaidres, kuriose buvo parodyta, kad užstrigus operacijoms, auga ir lentelės erdvės, ir indekso dydis. Ir toliau ataskaitoje buvo daugybė paslaugų, kurios supakuoja planšetinį kompiuterį. O kaip su indeksu?

Jie taip pat juos supakuoja.

Bet vakuumas neturi įtakos indeksui?

Kai kurie dirba su indeksu. Pavyzdžiui, pg_rapack, pgcompacttable. Vakuumas atkuria indeksus ir juos paveikia. Su VACUUM FULL idėja yra viską perrašyti, t. y. jis veikia su visais.

Ir antras klausimas. Nesuprantu, kodėl ataskaitos apie kopijas labai priklauso nuo pačios replikacijos. Man atrodė, kad ataskaitos yra skaitomos, o replikacija yra rašoma.

Kas sukelia replikacijos konfliktą? Mes turime meistrą, kuriame vyksta procesai. Pas mus vyksta automobilio dulkių siurblys. Ką iš tikrųjų daro automatinis vakuumas? Jis išpjauna kai kurias senas eilutes. Jei šiuo metu turime užklausą kopijoje, kuri skaito šias senas eilutes, o „Master“ įvyko situacija, kad automatinis vakuumas pažymėjo šias eilutes kaip galimas perrašyti, tada mes jas perrašėme. Ir mes gavome duomenų paketą, kai reikės perrašyti tas eilutes, kurių reikia užklausai replikoje, replikacijos procesas lauks jūsų sukonfigūruoto laiko. Tada PostgreSQL nuspręs, kas jam svarbiau. Ir replikacija jam yra svarbesnė nei užklausa, ir jis pateiks užklausą, kad atliktų šiuos pakeitimus kopijoje.

Andrejus, turiu klausimą. Ar šie nuostabūs grafikai, kuriuos rodėte pristatymo metu, yra kažkokio jūsų naudingumo darbo rezultatas? Kaip buvo sudaryti grafikai?

Tai paslauga Okmetras.

Ar tai komercinis produktas?

Taip. Tai komercinis produktas.

Šaltinis: www.habr.com

Добавить комментарий