Dæmigerðar villur í forritum sem leiða til uppþembu í postgresql. Andrey Salnikov

Ég legg til að þú lesir afrit skýrslunnar frá ársbyrjun 2016 eftir Andrey Salnikov „Dæmigerðar villur í forritum sem leiða til uppþembu í postgresql“

Í þessari skýrslu mun ég greina helstu villur í forritum sem koma upp á því stigi að hanna og skrifa umsóknarkóða. Og ég mun aðeins taka þær villur sem leiða til uppþembu í Postgresql. Að jafnaði er þetta upphafið á endalokum frammistöðu kerfisins í heild, þó að upphaflega hafi engar forsendur fyrir því verið sýnilegar.

Dæmigerðar villur í forritum sem leiða til uppþembu í postgresql. Andrey Salnikov

Gaman að taka á móti öllum! Þessi skýrsla er ekki eins tæknileg og sú fyrri frá félaga mínum. Þessi skýrsla er aðallega miðuð við bakendakerfisframleiðendur vegna þess að við erum með frekar mikinn fjölda viðskiptavina. Og þeir gera allir sömu mistökin. Ég skal segja þér frá þeim. Ég mun útskýra hvaða banvæna og slæma hluti þessi mistök leiða til.

Dæmigerðar villur í forritum sem leiða til uppþembu í postgresql. Andrey Salnikov

Hvers vegna eru mistök gerð? Þeir eru gerðir af tveimur ástæðum: af handahófi, kannski mun það ganga upp og vegna vanþekkingar á sumum aðferðum sem eiga sér stað á stigi milli gagnagrunnsins og forritsins, sem og í gagnagrunninum sjálfum.

Ég skal gefa þér þrjú dæmi með hræðilegum myndum af því hversu illa fór. Ég skal segja þér stuttlega frá vélbúnaðinum sem gerist þar. Og hvernig á að bregðast við þeim, hvenær þau gerðust og hvaða fyrirbyggjandi aðferðir á að nota til að koma í veg fyrir mistök. Ég mun segja þér frá hjálparverkfærunum og veita gagnlega tengla.

Dæmigerðar villur í forritum sem leiða til uppþembu í postgresql. Andrey Salnikov

Ég notaði prófunargagnagrunn þar sem ég var með tvær töflur. Önnur platan með reikningum viðskiptavina, hin með færslum á þessum reikningum. Og með nokkurri tíðni uppfærum við stöðuna á þessum reikningum.

Dæmigerðar villur í forritum sem leiða til uppþembu í postgresql. Andrey Salnikov

Upphafleg gögn plötunnar: hún er frekar lítil, 2 MB. Viðbragðstími fyrir gagnagrunninn og sérstaklega fyrir skiltið er líka mjög góður. Og nokkuð gott álag - 2 aðgerðir á sekúndu samkvæmt plötunni.

Dæmigerðar villur í forritum sem leiða til uppþembu í postgresql. Andrey Salnikov

Og í gegnum þessa skýrslu mun ég sýna þér línurit svo að þú getir greinilega skilið hvað er að gerast. Það verða alltaf 2 glærur með línuritum. Fyrsta glæran er það sem gerist almennt á þjóninum.

Og við þessar aðstæður sjáum við að við höfum í raun lítið merki. Vísitalan er lítil eða 2 MB. Þetta er fyrsta grafið til vinstri.

Meðalviðbragðstími á þjóninum er einnig stöðugur og stuttur. Þetta er grafið efst til hægri.

Grafið neðst til vinstri sýnir lengstu viðskiptin. Við sjáum að viðskipti eru fljót að ganga frá. Og sjálfvirka tómarúmið virkar ekki hér ennþá, því það var byrjunarpróf. Það mun halda áfram að virka og mun nýtast okkur vel.

Dæmigerðar villur í forritum sem leiða til uppþembu í postgresql. Andrey Salnikov

Önnur rennibrautin verður alltaf tileinkuð plötunni sem verið er að prófa. Í þessum aðstæðum uppfærum við stöðugt innstæður viðskiptavinarins. Og við sjáum að meðalviðbragðstími fyrir uppfærsluaðgerð er nokkuð góður, innan við millisekúnda. Við sjáum að örgjörvaauðlindir (þetta er grafið fyrir ofan hægra megin) er einnig neytt jafnt og frekar lítið.

Neðra línuritið til hægri sýnir hversu mikið rekstrar- og diskaminni við förum í gegnum í leit að þeirri línu sem við viljum áður en við uppfærum hana. Og fjöldi aðgerða samkvæmt merkinu er 2 á sekúndu eins og ég sagði í upphafi.

Dæmigerðar villur í forritum sem leiða til uppþembu í postgresql. Andrey Salnikov

Og nú höfum við harmleik. Einhverra hluta vegna er löngu gleymt viðskipti. Ástæðurnar eru venjulega allar banal:

  • Eitt af því algengasta er að við byrjuðum að fá aðgang að ytri þjónustu í forritakóðanum. Og þessi þjónusta svarar okkur ekki. Það er að segja, við opnuðum viðskipti, gerðum breytingu á gagnagrunninum og fórum úr forritinu í að lesa póst eða í aðra þjónustu innan innviða okkar og af einhverjum ástæðum svarar hún okkur ekki. Og fundur okkar er fastur í ástandi þar sem ekki er vitað hvenær það verður leyst.
  • Annað ástandið er þegar undantekning kom upp í kóðanum okkar af einhverjum ástæðum. Og í undantekningu afgreiddum við ekki lokun viðskiptanna. Og við enduðum með hangandi fundi með opnum viðskiptum.
  • Og það síðasta er líka nokkuð algengt mál. Þetta er lággæða kóða. Sumir rammar opna viðskipti. Það hangir og þú veist kannski ekki í forritinu að þú hafir það hangandi.

Hvert leiða svona hlutir?

Að því marki að töflur okkar og vísitölur byrja að bólgna verulega. Þetta eru nákvæmlega sömu uppblásna áhrifin. Fyrir gagnagrunninn mun þetta þýða að viðbragðstími gagnagrunnsins eykst mjög mikið og álagið á gagnagrunnsþjóninn eykst. Og þar af leiðandi mun umsókn okkar þjást. Vegna þess að ef þú eyddir 10 millisekúndum í kóðanum þínum í beiðni til gagnagrunnsins, 10 millisekúndum í rökfræði þína, þá tók aðgerðin þín 20 millisekúndur að klára. Og nú verður ástand þitt mjög sorglegt.

Og við skulum sjá hvað gerist. Grafið neðst til vinstri sýnir að við erum með löng lang viðskipti. Og ef við skoðum efra línuritið til vinstri sjáum við að stærð töflunnar okkar hefur skyndilega hoppað úr tveimur megabæti í 300 megabæti. Á sama tíma hefur gagnamagn í töflunni ekki breyst, þ.e.a.s. þar er frekar mikið sorp.

Dæmigerðar villur í forritum sem leiða til uppþembu í postgresql. Andrey Salnikov

Almennt ástand varðandi meðalviðbragðstíma netþjóna hefur einnig breyst um nokkrar stærðargráður. Það er, allar beiðnir á þjóninum fóru að falla alveg. Og á sama tíma voru innri Postgres ferli sett af stað í formi autovacuum, sem eru að reyna að gera eitthvað og neyta fjármagns.

Dæmigerðar villur í forritum sem leiða til uppþembu í postgresql. Andrey Salnikov

Hvað er í gangi með skiltið okkar? Það sama. Meðalviðbragðstími okkar samkvæmt skiltinu hefur hækkað um nokkrar stærðargráður. Sérstaklega með tilliti til neyttra auðlinda, sjáum við að álagið á örgjörvan hefur aukist mikið. Þetta er grafið efst til hægri. Og það hefur aukist vegna þess að örgjörvinn þarf að raða í gegnum fullt af gagnslausum línum í leit að þeirri sem þarf. Þetta er grafið neðst til hægri. Og fyrir vikið fór símtölum okkar á sekúndu að fækka mjög verulega, vegna þess að gagnagrunnurinn hafði ekki tíma til að vinna úr sama fjölda beiðna.

Dæmigerðar villur í forritum sem leiða til uppþembu í postgresql. Andrey Salnikov

Við þurfum að komast aftur til lífsins. Við förum á netið og komumst að því að löng viðskipti leiða til vandræða. Við finnum og drepum þessi viðskipti. Og allt er að verða eðlilegt hjá okkur. Allt virkar eins og það á að gera.

Við róuðumst en eftir smá stund förum við að taka eftir því að forritið virkar ekki eins og fyrir neyðartilvik. Beiðnir eru enn afgreiddar hægar og verulega hægar. Einn og hálfur til tvisvar sinnum hægari sérstaklega í mínu dæmi. Álagið á netþjóninn er líka meira en það var fyrir slysið.

Dæmigerðar villur í forritum sem leiða til uppþembu í postgresql. Andrey Salnikov

Og spurningin: "Hvað er að gerast með herstöðina á þessari stundu?" Og eftirfarandi aðstæður eiga sér stað með grunninn. Á viðskiptatöflunni geturðu séð að það hefur stöðvast og það eru í raun engin langtímaviðskipti. En stærð merkisins jókst banvænt við slysið. Og síðan hefur þeim ekki fækkað. Meðaltími á grunni hefur náð jafnvægi. Og svörin virðast koma nægilega vel á þeim hraða sem okkur er viðunandi. Autovacuum varð virkari og fór að gera eitthvað við skiltið, því það þarf að sigta í gegnum fleiri gögn.

Dæmigerðar villur í forritum sem leiða til uppþembu í postgresql. Andrey Salnikov

Nánar tiltekið, samkvæmt prófunarplötunni með reikningum, þar sem við breytum stöðunum: svartími fyrir beiðni virðist vera kominn í eðlilegt horf. En í raun er það einu og hálfu sinnum hærra.

Og af álaginu á örgjörvann sjáum við að álagið á örgjörvan hefur ekki farið aftur í tilskilið gildi fyrir hrun. Og ástæðurnar þar liggja einmitt í grafinu neðra hægra megin. Það sést að þarna er verið að leita að vissu minni. Það er, til að finna nauðsynlega línu, sóum við auðlindum gagnagrunnsþjónsins á meðan við flokkum gagnslaus gögn. Fjöldi viðskipta á sekúndu hefur náð jafnvægi.

Á heildina litið gott, en ástandið er verra en það var. Hreinsaðu niðurbrot gagnagrunns sem afleiðing af forritinu okkar sem vinnur með þessum gagnagrunni.

Dæmigerðar villur í forritum sem leiða til uppþembu í postgresql. Andrey Salnikov

Og til að skilja hvað er að gerast þarna, ef þú varst ekki í fyrri skýrslu, skulum við nú fá smá kenningu. Kenning um innra ferli. Af hverju bílaryksuga og hvað gerir það?

Bókstaflega stuttlega til skilnings. Á einhverjum tímapunkti höfum við borð. Við höfum raðir í töflunni. Þessar línur geta verið virkar, lifandi og það sem við þurfum núna. Þeir eru merktir með grænu á myndinni. Og það eru tímalínur sem þegar hafa verið unnar, hafa verið uppfærðar og nýjar færslur hafa birst á þeim. Og þeir eru merktir að þeir séu ekki lengur áhugaverðir fyrir gagnagrunninn. En þeir eru í töflunni vegna Postgres eiginleika.

Af hverju þarftu bílryksugu? Á einhverjum tímapunkti kemur sjálfvirka tómarúmið, opnar gagnagrunninn og spyr hann: „Vinsamlegast gefðu mér auðkenni elstu færslunnar sem er opin í gagnagrunninum. Gagnagrunnurinn skilar þessu auðkenni. Og sjálfvirka tómarúmið, sem treystir á það, raðar í gegnum línurnar í töflunni. Og ef hann sér að einhverjum línum var breytt með miklu eldri viðskiptum, þá hefur hann rétt á að merkja þær sem línur sem við getum endurnýtt í framtíðinni með því að skrifa þar ný gögn. Þetta er bakgrunnsferli.

Á þessum tíma höldum við áfram að vinna með gagnagrunninn og höldum áfram að gera nokkrar breytingar á töflunni. Og á þessar línur, sem við getum endurnýtt, skrifum við ný gögn. Og þannig fáum við hringrás, þ.e.a.s. allan tímann birtast þarna einhverjar dauðar gamlar línur, í staðinn fyrir þær skrifum við niður nýjar línur sem við þurfum. Og þetta er eðlilegt ástand fyrir PostgreSQL að virka.

Dæmigerðar villur í forritum sem leiða til uppþembu í postgresql. Andrey Salnikov

Hvað gerðist í slysinu? Hvernig varð þetta ferli þarna?

Við vorum með skilti í einhverju ástandi, sumt í beinni, sumar dauðaröð. Bílasúpan er komin. Hann spurði gagnagrunninn hver elsta viðskiptin okkar væru og hvert auðkenni hans væri. Ég fékk þetta auðkenni, sem gæti verið fyrir mörgum klukkustundum, kannski tíu mínútum síðan. Það fer eftir því hversu mikið álagið þú ert með á gagnagrunninum þínum. Og hann fór að leita að línum sem hann gæti merkt sem endurnýttar. Og ég fann ekki slíkar línur í töflunni okkar.

En á þessum tíma höldum við áfram að vinna með borðið. Við gerum eitthvað í því, uppfærum það, breytum gögnunum. Hvað ætti gagnagrunnurinn að gera á þessum tíma? Hún hefur ekkert val en að bæta nýjum línum við enda núverandi töflu. Og þannig byrjar borðstærðin okkar að bólgna.

Í raun og veru þurfum við grænar línur til að virka. En meðan á slíku vandamáli stendur kemur í ljós að hlutfall grænna lína er mjög lágt um alla töfluna.

Og þegar við framkvæmum fyrirspurn þarf gagnagrunnurinn að fara í gegnum allar línur: bæði rauðar og grænar, til að finna þá línu sem óskað er eftir. Og áhrif þess að blása upp borð með gagnslausum gögnum kallast „uppblásinn“, sem eyðir líka plássinu okkar. Mundu að það var 2 MB, það varð 300 MB? Breyttu nú megabæti í gígabæt og þú munt fljótt tapa öllum diskaauðlindum þínum.

Dæmigerðar villur í forritum sem leiða til uppþembu í postgresql. Andrey Salnikov

Hvaða afleiðingar gæti það haft fyrir okkur?

  • Í mínu dæmi stækkaði taflan og vísitalan 150 sinnum. Sumir viðskiptavina okkar hafa lent í fleiri banvænum tilfellum þegar þeir fóru einfaldlega að verða uppiskroppa með pláss.
  • Stærð borðanna sjálfrar mun aldrei minnka. Sjálfvirkt tómarúm getur í sumum tilfellum skorið af borðinu ef það eru aðeins dauðalínur. En þar sem það er stöðugur snúningur getur ein græn lína frjósa í lokin og ekki uppfærð á meðan allar hinar verða skrifaðar niður einhvers staðar í byrjun plötunnar. En þetta er svo ólíklegt að borðið þitt sjálft muni minnka að stærð, svo þú ættir ekki að vona það.
  • Gagnagrunnurinn þarf að raða í gegnum heilan helling af gagnslausum línum. Og við sóum diskaauðlindum, við sóum örgjörvaauðlindum og rafmagni.
  • Og þetta hefur bein áhrif á forritið okkar, því ef við eyddum 10 millisekúndum í beiðnina í upphafi, 10 millisekúndum í kóðann okkar, þá fórum við að eyða sekúndu í beiðnina í hruninu og 10 millisekúndum í kóðann, þ.e. magn í afköstum umsókna minnkaði. Og þegar slysið var leyst fórum við að eyða 20 millisekúndum í beiðni, 10 millisekúndum í kóða. Þetta þýðir að við lækkuðum enn um einn og hálft sinnum í framleiðni. Og þetta er allt vegna einnar viðskipta sem frosna, kannski okkur að kenna.
  • Og spurningin: „Hvernig getum við fengið allt til baka?“ þannig að allt sé í lagi hjá okkur og beiðnir berast jafnharðan og fyrir slysið.

Dæmigerðar villur í forritum sem leiða til uppþembu í postgresql. Andrey Salnikov

Í þessu skyni er ákveðin hringrás vinnu sem framkvæmt er.

Fyrst þurfum við að finna erfiðu töflurnar sem eru uppblásnar. Við skiljum að í sumum töflum er upptakan virkari, í öðrum minna virk. Og fyrir þetta notum við framlenginguna pgstattuple. Með því að setja upp þessa viðbót geturðu skrifað fyrirspurnir sem hjálpa þér að finna töflur sem eru frekar uppblásnar.

Þegar þú hefur fundið þessar töflur þarftu að þjappa þeim saman. Það eru nú þegar til tæki til þess. Í fyrirtækinu okkar notum við þrjú verkfæri. Hið fyrra er innbyggt VACUUM FULL. Hann er grimmur, harður og miskunnarlaus, en stundum er hann mjög gagnlegur. Pg_repack и pgcompacttable - Þetta eru tól frá þriðja aðila til að þjappa töflum. Og þeir fara varlega með gagnagrunninn.

Þau eru notuð eftir því hvað hentar þér betur. En ég segi þér frá þessu alveg í lokin. Aðalatriðið er að það eru þrjú verkfæri. Það er úr nógu að velja.

Eftir að við höfum leiðrétt allt og gengið úr skugga um að allt sé í lagi verðum við að vita hvernig á að koma í veg fyrir þetta ástand í framtíðinni:

  • Það er auðvelt að koma í veg fyrir það. Þú þarft að fylgjast með lengd lota á Master miðlara. Sérstaklega hættulegar lotur í aðgerðalausu í viðskiptastöðu. Þetta eru þeir sem bara opnuðu viðskipti, gerðu eitthvað og fóru, eða einfaldlega héngu, týndust í kóðanum.
  • Og fyrir þig, sem forritara, er mikilvægt að prófa kóðann þinn þegar þessar aðstæður koma upp. Það er ekki erfitt að gera. Þetta verður gagnlegt athugun. Þú munt forðast fjölda „barnalegra“ vandamála sem tengjast löngum viðskiptum.

Dæmigerðar villur í forritum sem leiða til uppþembu í postgresql. Andrey Salnikov

Í þessum línuritum langaði mig að sýna þér hvernig merkið og hegðun gagnagrunnsins breyttist eftir að ég fór í gegnum skiltið með VACUUM FULL í þessu tilfelli. Þetta er ekki framleiðsla fyrir mig.

Taflastærðin fór strax aftur í eðlilegt rekstrarástand, nokkur megabæt. Þetta hafði ekki mikil áhrif á meðalviðbragðstíma þjónsins.

Dæmigerðar villur í forritum sem leiða til uppþembu í postgresql. Andrey Salnikov

En sérstaklega fyrir prófunarmerkið okkar, þar sem við uppfærðum reikningsjöfnuð, sjáum við að meðalviðbragðstími fyrir beiðni um að uppfæra gögn í skiltinu var stytt niður í neyðartilvik. Tilföngin sem örgjörvinn notaði til að klára þessa beiðni lækkuðu einnig niður í stig fyrir hrun. Og neðra línuritið til hægri sýnir að nú finnum við nákvæmlega línuna sem við þurfum strax, án þess að fara í gegnum haugana af dauðu línum sem voru þar áður en borðið var þjappað saman. Og meðalbeiðnitíminn hélst um það bil á sama stigi. En hér hef ég frekar villu í vélbúnaðinum mínum.

Dæmigerðar villur í forritum sem leiða til uppþembu í postgresql. Andrey Salnikov

Hér endar fyrsta sagan. Það er algengast. Og það gerist fyrir alla, óháð reynslu viðskiptavinarins og hversu hæfir forritararnir eru. Fyrr eða síðar gerist þetta.

Önnur sagan, þar sem við dreifum álaginu og fínstillum netþjónaauðlindir

Dæmigerðar villur í forritum sem leiða til uppþembu í postgresql. Andrey Salnikov

  • Við erum þegar orðnir alvarlegir strákar. Og við skiljum að við eigum eftirmynd og það væri gott fyrir okkur að koma jafnvægi á álagið: skrifaðu til meistarans og lestu úr eftirmyndinni. Og venjulega kemur þessi staða upp þegar við viljum undirbúa nokkrar skýrslur eða ETL. Og fyrirtækin eru mjög ánægð með þetta. Hann vill endilega fá margvíslegar skýrslur með mörgum flóknum greiningargreinum.
  • Skýrslur taka margar klukkustundir, vegna þess að ekki er hægt að reikna flóknar greiningar á millisekúndum. Við, eins og hugrakkir krakkar, skrifum kóða. Í innsetningarforritinu gerum við upptökuna á meistaranum og framkvæmum skýrslurnar um eftirmyndina.
  • Að dreifa álaginu.
  • Allt virkar fullkomlega. Við erum frábærir.

Dæmigerðar villur í forritum sem leiða til uppþembu í postgresql. Andrey Salnikov

Og hvernig lítur þetta ástand út? Sérstaklega á þessum línuritum bætti ég einnig við tímalengd viðskipta frá eftirmyndinni fyrir viðskiptatímann. Öll önnur graf vísa aðeins til Master netþjónsins.

Á þessum tíma hafði skýrslunefndin mín stækkað. Þeir eru fleiri. Við sjáum að meðalviðbragðstími netþjónsins er stöðugur. Við sjáum að á eftirmyndinni erum við með langvarandi viðskipti sem standa yfir í 2 klukkustundir. Við sjáum hljóðláta virkni sjálfvirka tómarúmsins, sem vinnur dauðalínur. Og allt er í lagi með okkur.

Dæmigerðar villur í forritum sem leiða til uppþembu í postgresql. Andrey Salnikov

Nánar tiltekið, samkvæmt prófuðu plötunni, höldum við áfram að uppfæra reikningsjöfnuð þar. Og við höfum líka stöðugan viðbragðstíma fyrir beiðnum, stöðuga auðlindanotkun. Allt er í lagi með okkur.

Dæmigerðar villur í forritum sem leiða til uppþembu í postgresql. Andrey Salnikov

Allt er í lagi þar til þessar skýrslur byrja að skjóta til baka vegna átaka við afritun. Og þeir skjóta til baka með reglulegu millibili.

Við förum á netið og byrjum að lesa hvers vegna þetta er að gerast. Og við finnum lausn.

Fyrsta lausnin er að auka leynd afritunar. Við vitum að skýrslan okkar stendur í 3 klukkustundir. Við stillum afritunartöfina á 3 klukkustundir. Við erum að setja allt af stað, en við höldum áfram að eiga í vandræðum með að stundum sé hætt við tilkynningar.

Við viljum að allt sé fullkomið. Við klifum lengra. Og við fundum flotta stillingu á netinu - hot_standby_feedback. Kveikjum á því. Hot_standby_feedback gerir okkur kleift að halda aftur af sjálfvirku tómarúminu á Master. Þannig losnum við algjörlega við afritunarárekstra. Og allt gengur vel hjá okkur með skýrslur.

Dæmigerðar villur í forritum sem leiða til uppþembu í postgresql. Andrey Salnikov

Og hvað er að gerast með Master netþjóninn á þessum tíma? Og við erum í algjörum vandræðum með Master netþjóninn. Núna erum við að sjá línuritin þegar ég hef báðar þessar stillingar virkar. Og við sjáum að lotan á eftirmyndinni okkar byrjaði einhvern veginn að hafa áhrif á ástandið á Master netþjóninum. Hún hefur áhrif vegna þess að hún gerði hlé á sjálfvirku tómarúminu, sem hreinsar dauðalínurnar. Stærð borðsins okkar hefur rokið upp aftur. Meðalframkvæmdartími fyrirspurna í öllum gagnagrunninum rauk einnig upp. Autovacuums hertust aðeins.

Dæmigerðar villur í forritum sem leiða til uppþembu í postgresql. Andrey Salnikov

Nánar tiltekið, af plötunni okkar, sjáum við að gagnauppfærslan á henni hljóp líka til skýjanna. Örgjörvanotkun hefur að sama skapi aukist mikið. Við erum aftur að fara í gegnum mikinn fjölda dauðra, gagnslausra línur. Og viðbragðstími fyrir þetta skilti og fjöldi viðskipta hefur lækkað.

Dæmigerðar villur í forritum sem leiða til uppþembu í postgresql. Andrey Salnikov

Hvernig mun það líta út ef við vitum ekki hvað ég var að tala um áður?

  • Við byrjum að leita að vandamálum. Ef við lentum í vandræðum í fyrri hlutanum vitum við að þetta gæti verið vegna langra viðskipta og farið til meistarans. Við eigum í vandræðum með meistarann. Pylsur hann. Hann hitnar, hleðslumeðaltal hans er um hundrað.
  • Beiðnir þar eru hægar en við sjáum engin langvarandi viðskipti þar. Og við skiljum ekki hvað er að. Við skiljum ekki hvert við eigum að leita.
  • Við athugum netþjónabúnað. Kannski hrundi árás okkar. Kannski er minnislykillinn okkar útbrunninn. Já, allt getur gerst. En nei, serverarnir eru nýir, allt virkar fínt.
  • Allir eru í gangi: stjórnendur, verktaki og leikstjóri. Ekkert hjálpar.
  • Og á einhverjum tímapunkti byrjar allt allt í einu að laga sig.

Dæmigerðar villur í forritum sem leiða til uppþembu í postgresql. Andrey Salnikov

Á þessum tíma var beiðnin um eftirmynd okkar afgreidd og hún skilin eftir. Við fengum skýrsluna. Viðskipti eru enn ánægð. Eins og þú sérð hefur skiltið okkar stækkað aftur og er ekki að fara að minnka. Á línuritinu með lotum skildi ég eftir hluta af þessum löngu viðskiptum frá eftirlíkingu svo að þú getir metið hversu langan tíma það tekur þar til ástandið kemst á jafnvægi.

Þinginu er lokið. Og aðeins eftir nokkurn tíma kemur þjónninn meira og minna í röð. Og meðalviðbragðstími beiðna á Master netþjóninum fer aftur í eðlilegt horf. Vegna þess að loksins hefur sjálfvirka tómarúmið tækifæri til að hreinsa út og merkja þessar dauðalínur. Og hann fór að vinna vinnuna sína. Og hversu fljótt hann gerir það, svo fljótt munum við koma í röð.

Dæmigerðar villur í forritum sem leiða til uppþembu í postgresql. Andrey Salnikov

Samkvæmt prófuðu spjaldtölvunni, þar sem við uppfærum reikningsjöfnuð, sjáum við nákvæmlega sömu mynd. Meðaluppfærslutími reiknings er einnig smám saman að verða eðlilegur. Auðlindirnar sem örgjörvinn notar minnka einnig. Og fjöldi viðskipta á sekúndu fer aftur í eðlilegt horf. En aftur erum við komin í eðlilegt horf, ekki það sama og við vorum fyrir slysið.

Dæmigerðar villur í forritum sem leiða til uppþembu í postgresql. Andrey Salnikov

Hvað sem því líður fáum við frammistöðusamdrátt eins og í fyrra tilvikinu einu og hálfu til tvisvar sinnum og stundum oftar.

Við virðumst hafa gert allt rétt. Dreifðu álaginu. Búnaðurinn er ekki aðgerðalaus. Við skiptum beiðnum eftir hugum okkar en samt fór allt illa.

  • Ekki virkja hot_standby_feedback? Já, það er ekki mælt með því að kveikja á því án sérstaklega sterkra ástæðna. Vegna þess að þessi útúrsnúningur hefur bein áhrif á Master netþjóninn og stöðvar rekstur autovacuum þar. Með því að virkja það á einhverri eftirmynd og gleyma því geturðu drepið meistarann ​​og lent í miklum vandræðum með forritið.
  • Auka max_standby_streaming_delay? Já, fyrir skýrslur er þetta satt. Ef þú ert með þriggja tíma skýrslu og þú vilt ekki að hún hrynji vegna afritunarátaka, þá skaltu einfaldlega auka seinkunina. Langtímaskýrsla krefst aldrei gagna sem hafa borist í gagnagrunninn núna. Ef þú hefur það í þrjár klukkustundir, þá ertu að keyra það í einhvern gamalt gagnatímabil. Og fyrir þig, hvort það er þriggja tíma seinkun eða sex tíma seinkun mun ekki skipta neinu máli, en þú munt fá skýrslur stöðugt og munt ekki eiga í neinum vandræðum með að falla.
  • Auðvitað þarftu að stjórna löngum lotum á eftirmyndum, sérstaklega ef þú ákveður að virkja hot_standby_feedback á eftirmynd. Því allt getur gerst. Við gáfum þróunaraðilanum þessa eftirmynd svo hann gæti prófað beiðnirnar. Hann skrifaði vitlausa beiðni. Hann setti það af stað og fór að drekka te, og við fengum hinn stofnaða meistara. Eða kannski settum við rangt forrit þar inn. Aðstæður eru margvíslegar. Fylgjast verður jafn vel með fundum á eftirlíkingum og á meistaranum.
  • Og ef þú ert með hraðar og langar fyrirspurnir um eftirmyndir, þá er í þessu tilfelli betra að skipta þeim til að dreifa álaginu. Þetta er tengill á streaming_delay. Fyrir hraðvirka skaltu hafa eina eftirmynd með lítilli afritunartöf. Fyrir langvarandi skýrslubeiðnir skaltu hafa eftirmynd sem getur dregist um 6 klukkustundir eða á dag. Þetta er alveg eðlilegt ástand.

Við útrýmum afleiðingunum á sama hátt:

  • Við finnum uppblásnar töflur.
  • Og við þjöppum því saman með þægilegasta tækinu sem hentar okkur.

Seinni sagan endar hér. Við skulum halda áfram að þriðju sögunni.

Dæmigerðar villur í forritum sem leiða til uppþembu í postgresql. Andrey Salnikov

Einnig nokkuð algengt hjá okkur þar sem við búum til fólksflutninga.

Dæmigerðar villur í forritum sem leiða til uppþembu í postgresql. Andrey Salnikov

  • Sérhver hugbúnaðarvara er að vaxa. Kröfurnar til þess eru að breytast. Í öllu falli viljum við þróast. Og það gerist að við þurfum að uppfæra gögnin í töflunni, nefnilega að keyra uppfærslu hvað varðar flutning okkar fyrir nýja virkni sem við erum að kynna sem hluta af þróun okkar.
  • Gamla gagnasniðið er ekki fullnægjandi. Segjum að við snúum okkur nú að annarri töflunni, þar sem ég er með færslur á þessum reikningum. Og segjum að þeir væru í rúblum og við ákváðum að auka nákvæmni og gera það í kopekjum. Og fyrir þetta þurfum við að gera uppfærslu: margfaldaðu reitinn með færsluupphæðinni með hundrað.
  • Í heimi nútímans notum við sjálfvirk gagnagrunnsútgáfustýringartæki. Segjum sem svo Liquibase. Við skráum flutning okkar þangað. Við prófum það á prófunarstöðinni okkar. Allt er í lagi. Uppfærslan er að fara í gegn. Það lokar fyrir vinnu í smá stund, en við fáum uppfærð gögn. Og við getum sett af stað nýja virkni á þessu. Allt var prófað og athugað. Allt var staðfest.
  • Við unnum skipulagða vinnu og framkvæmdum fólksflutninga.

Dæmigerðar villur í forritum sem leiða til uppþembu í postgresql. Andrey Salnikov

Hér er flutningurinn með uppfærslunni sem kynnt er fyrir framan þig. Þar sem þetta eru reikningsfærslurnar mínar var platan 15 GB. Og þar sem við uppfærum hverja línu tvöfölduðum við stærð töflunnar með uppfærslunni, vegna þess að við endurskrifuðum hverja línu.

Dæmigerðar villur í forritum sem leiða til uppþembu í postgresql. Andrey Salnikov

Við flutninginn gátum við ekki gert neitt við þessa plötu, vegna þess að allar beiðnir á hana voru settar í biðröð og beðið þar til þessari uppfærslu var lokið. En hér vil ég vekja athygli þína á tölunum sem eru á lóðrétta ásnum. Það er, við höfum að meðaltali beiðnitíma fyrir flutning sem er um það bil 5 millisekúndur og álag á örgjörva, fjöldi blokkaðgerða til að lesa diskaminni er minni en 7,5.

Dæmigerðar villur í forritum sem leiða til uppþembu í postgresql. Andrey Salnikov

Við framkvæmdum flutninginn og lentum í vandræðum aftur.

Flutningurinn gekk vel, en:

  • Nú tekur gamla virknin lengri tíma að klára.
  • Borðið stækkaði aftur.
  • Álagið á netþjóninn varð aftur meira en áður.
  • Og auðvitað erum við enn að fikta í virkninni sem virkaði vel, við höfum bætt hana aðeins.

Og þetta er aftur uppþemba, sem aftur eyðileggur líf okkar.

Dæmigerðar villur í forritum sem leiða til uppþembu í postgresql. Andrey Salnikov

Hér sýni ég fram á að taflan, eins og fyrri tvö tilvikin, mun ekki fara aftur í fyrri stærðir. Meðalálag á netþjóni virðist vera fullnægjandi.

Dæmigerðar villur í forritum sem leiða til uppþembu í postgresql. Andrey Salnikov

Og ef við snúum okkur að töflunni með reikningum munum við sjá að meðalbeiðnitími hefur tvöfaldast fyrir þessa töflu. Álagið á örgjörvann og fjöldi lína sem flokkaður var í minni fór yfir 7,5 en var lægri. Og það hoppaði 2 sinnum þegar um örgjörva var að ræða, 1,5 sinnum þegar um var að ræða blokkaraðgerðir, þ.e.a.s. við fengum skerðingu á frammistöðu miðlara. Og þar af leiðandi - hnignun á frammistöðu umsóknar okkar. Á sama tíma hélst fjöldi símtala um það bil á sama stigi.

Dæmigerðar villur í forritum sem leiða til uppþembu í postgresql. Andrey Salnikov

Og aðalatriðið hér er að skilja hvernig á að gera slíka flutninga rétt. Og það þarf að gera þær. Við gerum þessar flutningar nokkuð stöðugt.

  • Svo miklir fólksflutningar gerast ekki sjálfkrafa. Þeir verða alltaf að vera undir stjórn.
  • Nauðsynlegt er að hafa eftirlit með fróðum aðila. Ef þú ert með DBA í liðinu þínu, láttu DBA gera það. Það er hans starf. Ef ekki, láttu þá reyndasta manninn gera það, sem kann að vinna með gagnagrunna.
  • Nýtt gagnagrunnsskema, jafnvel þótt við uppfærum einn dálk, undirbúum við okkur alltaf í áföngum, þ.e.a.s. fyrirfram áður en nýja útgáfan af forritinu er sett í notkun:
  • Nýjum reitum er bætt við þar sem við munum skrá uppfærð gögn.
  • Við flytjum gögn af gamla reitnum yfir á nýja reitinn í litlum hlutum. Af hverju erum við að þessu? Í fyrsta lagi stjórnum við alltaf ferli þessa ferlis. Við vitum að við höfum þegar flutt svo margar lotur og við eigum svo margar eftir.
  • Og önnur jákvæðu áhrifin eru þau að á milli hverrar slíkrar lotu lokum við viðskiptunum, opnum nýjan, og þetta gerir sjálfvirka tómarúminu kleift að vinna í samræmi við plötuna, merkjum tímalínur til endurnotkunar.
  • Fyrir línurnar sem munu birtast á meðan forritið er í gangi (við erum enn með gamla forritið í gangi), bætum við kveikju sem skrifar ný gildi í nýja reiti. Í okkar tilviki er þetta margföldun með hundrað af gamla gildinu.
  • Ef við erum algjörlega þrjósk og viljum sama reitinn, þá endurnefna við reitina einfaldlega, þegar öllum flutningum er lokið og áður en ný útgáfa af forritinu er sett út. Hinir gömlu fá eitthvað tilbúið nafn og nýju reitirnir eru endurnefndir í þá gömlu.
  • Og aðeins eftir það ræsum við nýja útgáfu af forritinu.

Og á sama tíma munum við ekki fá uppþembu og munum ekki þjást hvað varðar frammistöðu.

Hér endar þriðja sagan.

Dæmigerðar villur í forritum sem leiða til uppþembu í postgresql. Andrey 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

Og nú aðeins meiri smáatriði um verkfærin sem ég nefndi í fyrstu sögunni.

Áður en þú leitar að uppþembu þarftu að setja upp viðbótina pgstattuple.

Svo að þú þurfir ekki að koma með fyrirspurnir höfum við þegar skrifað þessar fyrirspurnir í vinnu okkar. Þú getur notað þau. Hér eru tvær beiðnir.

  • Það fyrsta tekur töluvert langan tíma að virka, en það mun sýna þér nákvæm uppþembagildi úr töflunni.
  • Sá seinni vinnur hraðar og er mjög áhrifaríkur þegar þú þarft að meta fljótt hvort það sé uppþemba eða ekki samkvæmt töflunni. Og þú ættir líka að skilja að uppþemba er alltaf til staðar í Postgres borði. Þetta er eiginleiki MVCC líkansins.
  • Og 20% ​​uppþemba er eðlilegt fyrir borð í flestum tilfellum. Það er, þú ættir ekki að hafa áhyggjur og þjappa þessari töflu.

Við komumst að því hvernig á að bera kennsl á töflur sem eru bólgnar með gagnslausum gögnum.

Nú um hvernig á að laga uppþembu:

  • Ef við erum með litla spjaldtölvu og góða diska, það er að segja á spjaldtölvu upp í gígabæt, er alveg hægt að nota VACUUM FULL. Hann mun taka einkalás frá þér á borðinu í nokkrar sekúndur og allt í lagi, en hann mun gera allt hratt og harkalega. Hvað gerir VACUUM FULL? Það tekur einkalás á borðinu og endurskrifar lifandi raðir úr gömlu borðunum yfir í nýja borðið. Og í lokin kemur hann í stað þeirra. Það eyðir gömlum skrám og skiptir þeim gömlu út fyrir nýjar. En meðan á vinnu sinni stendur tekur það einkarétt á borðinu. Þetta þýðir að þú getur ekki gert neitt við þessa töflu: Hvorki skrifað í hana né lesið í hana né breytt henni. Og VACUUM FULL krefst viðbótar diskpláss til að skrifa gögn.
  • Næsta verkfæri pg_repack. Í meginreglunni minnir það mjög á VACUUM FULL, því það endurskrifar einnig gögn úr gömlum skrám yfir í nýjar og kemur í stað þeirra í töflunni. En á sama tíma tekur það ekki einkalás á borðið strax í upphafi vinnu sinnar, heldur tekur það aðeins á því augnabliki sem það hefur þegar tilbúin gögn til að skipta um skrárnar. Kröfur diskaauðlinda þess eru svipaðar og VACUUM FULL. Þú þarft meira pláss og það er stundum mikilvægt ef þú ert með terabæta töflur. Og það er frekar örgjörva-svangt vegna þess að það virkar virkan með I/O.
  • Þriðja tólið er pgcompacttable. Það er varkárara með auðlindir vegna þess að það vinnur eftir aðeins mismunandi meginreglum. Meginhugmynd pgcompacttable er að það færir allar lifandi línur í byrjun töflunnar með því að nota uppfærslur í töflunni. Og svo hleypur það tómarúm á þessu borði, því við vitum að við höfum lifandi raðir í upphafi og dauðar raðir í lokin. Og tómarúmið sjálft klippir þetta skott af, þ.e.a.s. það þarf ekki mikið viðbótarpláss. Og á sama tíma er enn hægt að kreista það hvað varðar fjármagn.

Allt með verkfærum.

Dæmigerðar villur í forritum sem leiða til uppþembu í postgresql. Andrey Salnikov

Ef þér finnst uppblásinn umræðuefnið áhugavert hvað varðar að kafa lengra inn, þá eru hér nokkrir gagnlegir tenglar:

Ég reyndi meira til að sýna hryllingssögu fyrir þróunaraðila, vegna þess að þeir eru beinir viðskiptavinir okkar gagnagrunna og verða að skilja hvað og hvaða aðgerðir leiða til. Ég vona að mér hafi tekist það. Takk fyrir athyglina!

spurningar

Takk fyrir skýrsluna! Þú talaðir um hvernig þú getur greint vandamál. Hvernig er hægt að vara þá við? Það er að segja, ég hafði aðstæður þar sem beiðnir héngu ekki aðeins vegna þess að þeir fengu aðgang að einhverri ytri þjónustu. Þetta voru bara villtir liðir. Það voru örsmáar, meinlausar beiðnir sem stóðu yfir í einn dag og fóru síðan að gera eitthvað bull. Semsagt mjög svipað því sem þú lýsir. Hvernig á að fylgjast með þessu? Sitja og horfa stöðugt á hvaða beiðni er föst? Hvernig er hægt að koma í veg fyrir þetta?

Í þessu tilviki er þetta verkefni fyrir stjórnendur fyrirtækisins, ekki endilega fyrir DBA.

Ég er stjórnandi.

PostgreSQL er með útsýni sem kallast pg_stat_activity sem sýnir hangandi fyrirspurnir. Og þú getur séð hversu lengi það hangir þar.

Þarf ég að koma inn og skoða á 5 mínútna fresti?

Settu upp cron og athugaðu. Ef þú ert með langtímabeiðni skaltu skrifa bréf og það er það. Það er, þú þarft ekki að horfa með augunum, það er hægt að gera það sjálfvirkt. Þú færð bréf, þú bregst við því. Eða þú getur skotið sjálfkrafa.

Eru einhverjar augljósar ástæður fyrir því að þetta gerist?

Ég hef skráð nokkrar. Önnur flóknari dæmi. Og það getur verið samtal í langan tíma.

Takk fyrir skýrsluna! Mig langaði að útskýra pg_repack tólið. Ef hún gerir ekki einkalás, þá...

Hún gerir einkalás.

... þá gæti ég hugsanlega tapað gögnum. Ætti umsóknin mín ekki að taka upp neitt á þessum tíma?

Nei, það virkar snurðulaust með töflunni, þ.e.a.s. pg_repack flytur fyrst allar lifandi línur sem eru til. Þar kemur náttúrulega einhvers konar innkoma inn í töfluna. Hann er bara að henda þessum hestahala út.

Semsagt, gerir hann það í raun og veru á endanum?

Að lokum tekur hann einkalás til að skipta um þessar skrár.

Verður það hraðar en VACUUM FULL?

VACUUM FULL, um leið og það byrjaði, tók strax einkarétt læsingu. Og þangað til hann gerir allt mun hann ekki sleppa henni. Og pg_repack tekur eingöngu læsingu þegar skipt er um skrá. Á þessari stundu muntu ekki skrifa þar, en gögnin munu ekki glatast, allt verður í lagi.

Halló! Þú talaðir um rekstur bílryksugu. Það var graf með rauðum, gulum og grænum skráningarhólfum. Það er að segja gula - hann merkti þá sem eytt. Og þar af leiðandi má skrifa eitthvað nýtt inn í þá?

Já. Postgres eyðir ekki línum. Hann hefur slíka sérstöðu. Ef við uppfærðum línu merktum við þá gömlu sem eytt. Auðkenni færslunnar sem breytti þessari línu birtist þar og við skrifum nýja línu. Og við höfum fundi sem gætu hugsanlega lesið þær. Á einhverjum tímapunkti verða þeir nokkuð gamlir. Og kjarninn í því hvernig autovacuum virkar er að það fer í gegnum þessar línur og merkir þær sem óþarfa. Og þú getur skrifað yfir gögn þar.

Ég skil. En það er ekki það sem spurningin snýst um. Ég kláraði ekki. Gerum ráð fyrir að við höfum töflu. Það hefur svið af breytilegri stærð. Og ef ég reyni að setja eitthvað nýtt inn gæti það einfaldlega ekki passað inn í gamla klefann.

Nei, alla vega er öll línan uppfærð þar. Postgres hefur tvö gagnageymslulíkön. Það velur úr gagnategundinni. Það eru gögn sem eru geymd beint í töflunni og það eru líka tos gögn. Þetta er mikið magn af gögnum: texti, json. Þau eru geymd á aðskildum plötum. Og samkvæmt þessum töflum kemur sama sagan með uppþembu, þ.e.a.s. allt er eins. Þeir eru bara skráðir sérstaklega.

Takk fyrir skýrsluna! Er ásættanlegt að nota fyrirspurnir um tímamörk yfirlýsingar til að takmarka tímalengd?

Mjög ásættanlegt. Við notum þetta alls staðar. Og þar sem við höfum ekki okkar eigin þjónustu, bjóðum við upp á fjarstuðning, við erum með töluvert úrval af viðskiptavinum. Og allir eru alveg sáttir við þetta. Það er, við erum með cron störf sem athuga. Lengd fundanna er einfaldlega samið við viðskiptavininn, áður en við erum ekki sammála. Það gæti verið mínúta, það gæti verið 10 mínútur. Það fer eftir álagi á undirstöðu og tilgangi þess. En við notum öll pg_stat_activity.

Takk fyrir skýrsluna! Ég er að reyna að nota skýrslu þína á umsóknir mínar. Og það virðist sem við hefjum viðskipti alls staðar og klárum það greinilega alls staðar. Ef það er einhver undantekning, þá á afturköllun enn sér stað. Og svo fór ég að hugsa. Þegar öllu er á botninn hvolft getur verið að viðskiptin hafi ekki beinlínis byrjað. Þetta er líklega vísbending fyrir stelpuna. Ef ég uppfæri bara færslu, byrjar viðskiptin í PostgreSQL og klárast aðeins þegar tengingin er aftengd?

Ef þú ert að tala núna um forritastigið, þá fer það eftir reklum sem þú ert að nota, á ORM sem er notað. Það eru margar stillingar þarna. Ef þú ert með sjálfvirka skuldbindingu virkt, þá byrja viðskipti þar og lokast strax.

Það er, það lokar strax eftir uppfærsluna?

Það fer eftir stillingum. Ég nefndi eina stillingu. Þetta er sjálfvirk skuldbinding. Það er frekar algengt. Ef það er virkt, þá hefur færslan opnað og lokað. Nema þú hafir beinlínis sagt „byrja viðskipti“ og „loka viðskiptum“, en einfaldlega settir beiðni inn í fundinn.

Halló! Takk fyrir skýrsluna! Ímyndum okkur að við séum með gagnagrunn sem er að bólgna og bólgna og þá klárast plássið á þjóninum. Eru einhver tæki til að laga þetta ástand?

Það þarf að fylgjast vel með plássinu á þjóninum.

DBA fór til dæmis í te, var á úrræði o.s.frv.

Þegar skráarkerfi er búið til verður að minnsta kosti til einhvers konar öryggisafrit þar sem gögn eru ekki skrifuð.

Hvað ef það er alveg undir núlli?

Þar er það kallað frátekið pláss, þ.e. það er hægt að losa það og eftir því hversu stórt það var búið til færðu laust pláss. Sjálfgefið veit ég ekki hversu margir þeir eru. Og í öðru tilviki, skilaðu diskum þannig að þú hafir pláss til að framkvæma endurbyggjandi aðgerð. Þú getur eytt einhverri töflu sem þú ert viss um að þú þurfir ekki.

Eru einhver önnur verkfæri?

Það er alltaf handsmíðað. Og staðbundið kemur í ljós hvað er best að gera þar, því sum gögn eru mikilvæg og önnur ekki mikilvæg. Og fyrir hvern gagnagrunn og forritið sem vinnur með hann fer það eftir viðskiptum. Það er alltaf ákveðið á staðnum.

Takk fyrir skýrsluna! Ég er með tvær spurningar. Í fyrsta lagi sýndir þú glærur sem sýndu að þegar færslur eru fastar stækkar bæði borðrýmisstærðin og vísitölustærðin. Og lengra á skýrslunni var fullt af tólum sem pakka spjaldtölvunni. Hvað með vísitöluna?

Þeir pakka þeim líka.

En tómarúmið hefur ekki áhrif á vísitöluna?

Sumir vinna með vísitölu. Til dæmis, pg_rapack, pgcompacttable. Tómarúmið endurskapar vísitölurnar og hefur áhrif á þær. Með VACUUM FULL er hugmyndin að skrifa yfir allt, þ.e.a.s. það virkar með öllum.

Og seinni spurningin. Ég skil ekki hvers vegna skýrslur um eftirlíkingar ráðast svona mikið af afrituninni sjálfri. Mér virtist sem skýrslur væru lesnar og afritun er ritun.

Hvað veldur afritunarátökum? Við höfum meistara sem ferlar eiga sér stað. Við erum með bílryksugu í gangi. Hvað gerir sjálfvirkt tómarúm í raun? Hann er að klippa út gamlar línur. Ef á þessum tíma höfum við beiðni um eftirlíkinguna sem les þessar gömlu línur, og á meistaranum kom upp sú staða að sjálftæmdu lofttæmi merkti þessar línur sem mögulegar yfirskrift, þá skrifuðum við yfir þær. Og við fengum gagnapakka, þegar við þurfum að endurskrifa þessar línur sem beiðnin þarf á eftirmyndinni, mun afritunarferlið bíða eftir tímamörkunum sem þú stilltir. Og þá mun PostgreSQL ákveða hvað er mikilvægara fyrir það. Og afritun er mikilvægari fyrir hann en beiðnin, og hann mun skjóta beiðninni til að gera þessar breytingar á eftirmyndinni.

Andrey, ég er með spurningu. Þessi frábæru línurit sem þú sýndir á kynningunni, eru þetta afrakstur vinnu einhvers konar nytja þíns? Hvernig voru línuritin gerð?

Þetta er þjónusta Okmeter.

Er þetta verslunarvara?

Já. Þetta er verslunarvara.

Heimild: www.habr.com

Bæta við athugasemd