{"id":81089,"date":"2020-05-11T01:42:24","date_gmt":"2020-05-10T23:42:24","guid":{"rendered":"https:\/\/prohoster.info\/blog\/administrirovanie\/tipovye-oshibki-v-prilozheniyah-kotorye-vedut-k-bloat-v-postgresql-andrej-salnikov"},"modified":"2020-05-11T01:42:24","modified_gmt":"2020-05-10T23:42:24","slug":"tipovye-oshibki-v-prilozheniyah-kotorye-vedut-k-bloat-v-postgresql-andrej-salnikov","status":"publish","type":"post","link":"https:\/\/prohoster.info\/ro\/blog\/administrirovanie\/tipovye-oshibki-v-prilozheniyah-kotorye-vedut-k-bloat-v-postgresql-andrej-salnikov","title":{"rendered":"Erorile tipice \u00een aplica\u021bii care duc la bloat \u00een PostgreSQL. Andrei Salnikov","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p><strong>V\u0103 invit s\u0103 consulta\u021bi transcrierea raportului din \u00eenceputul anului 2016 al lui Andrei Salnikov \"Erorile tipice \u00een aplica\u021bii care conduc la bloat \u00een PostgreSQL\"<\/strong><\/p>\n<p><\/p>\n<p>\u00cen aceast\u0103 prezentare voi analiza principalele erori \u00een aplica\u021bii care apar \u00een etapa de design \u0219i scriere a codului aplica\u021biei. Voi lua \u00een considerare doar acele erori care duc la bloat \u00een PostgreSQL. De regul\u0103, aceasta este \u00eenceputul sf\u00e2r\u0219itului performan\u021bei sistemului dumneavoastr\u0103 \u00een ansamblu, de\u0219i ini\u021bial nu au fost vizibile semne \u00een acest sens.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Erorile tipice \u00een aplica\u021bii care duc la bloat \u00een PostgreSQL. Andrei Salnikov\" src=\"\/wp-content\/uploads\/2020\/05\/a9e199bfe2e01c76966b32868790f8f0.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<p>Bun\u0103 tuturor! Aceast\u0103 prezentare nu este la fel de tehnic\u0103 ca cea anterioar\u0103 a colegului meu. Aceast\u0103 prezentare se concentreaz\u0103 \u00een principal pe dezvoltatorii de sisteme de backend, deoarece avem un num\u0103r destul de mare de clien\u021bi. \u0218i to\u021bi fac acelea\u0219i gre\u0219eli. Voi vorbi despre ele. Voi explica la ce rezult\u0103 aceste gre\u0219eli fatale \u0219i grave. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Erorile tipice \u00een aplica\u021bii care duc la bloat \u00een PostgreSQL. Andrei Salnikov\" src=\"\/wp-content\/uploads\/2020\/05\/c6c84dbafc595ae3068cd8bf804ccee7.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>De ce se fac erori? Ele apar din dou\u0103 motive: pe de o parte, pe baza unei atitudini de genul \u201epoate va merge\u201d \u0219i, pe de alt\u0103 parte, din ignoran\u021ba unor mecanisme care au loc la nivelul dintre baz\u0103 \u0219i aplica\u021bie, precum \u0219i \u00een baza de date \u00een sine. <\/p>\n<p><\/p>\n<p>Voi prezenta trei exemple cu imagini \u00eengrozitoare despre cum totul a ajuns r\u0103u. Voi explica pe scurt mecanismul care se desf\u0103\u0219oar\u0103 acolo. \u0218i cum s\u0103 lupt\u0103m cu ele atunci c\u00e2nd apar \u0219i ce metode preventive trebuie folosite pentru a evita erorile. Voi vorbi despre instrumente auxiliare \u0219i voi oferi linkuri utile. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Erorile tipice \u00een aplica\u021bii care duc la bloat \u00een PostgreSQL. Andrei Salnikov\" src=\"\/wp-content\/uploads\/2020\/05\/b0230d992f5b44f0e542df2e4b4d526f.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Am folosit o baz\u0103 de date de test, unde am avut dou\u0103 tabele. Un tabel cu facturile clien\u021bilor, iar cel\u0103lalt cu opera\u021biunile legate de aceste facturi. \u0218i la anumite intervale de timp actualiz\u0103m soldurile acestor facturi.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Erorile tipice \u00een aplica\u021bii care duc la bloat \u00een PostgreSQL. Andrei Salnikov\" src=\"\/wp-content\/uploads\/2020\/05\/1d2a21278b095b07546e1bb870819dbf.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Datele ini\u021biale ale tabelului: este destul de mic, 2 MB. Timpul de r\u0103spuns al bazei \u0219i pentru tabelul specific este, de asemenea, foarte bun. \u0218i o sarcin\u0103 destul de bun\u0103 \u2013 2000 de opera\u021biuni pe secund\u0103 pe tabel.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Erorile tipice \u00een aplica\u021bii care duc la bloat \u00een PostgreSQL. Andrei Salnikov\" src=\"\/wp-content\/uploads\/2020\/05\/dea5a4b1ac7952f8cfed0e2e1cfc10dd.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Pe parcursul acestei prezent\u0103ri v\u0103 voi ar\u0103ta grafice pentru a fi clar ce se \u00eent\u00e2mpl\u0103. Vor fi \u00eentotdeauna dou\u0103 diapozitive cu grafice. Primul diapozitiv va ar\u0103ta ce se \u00eent\u00e2mpl\u0103 \u00een general pe server. <\/p>\n<p><\/p>\n<p>\u00cen aceast\u0103 situa\u021bie vedem c\u0103 tabelul nostru este \u00eentr-adev\u0103r de dimensiuni mici. Indexul este mic, de 2 MB. Acesta este primul grafic din st\u00e2nga. <\/p>\n<p><\/p>\n<p>Timpul mediu de r\u0103spuns al serverului este, de asemenea, stabil \u0219i mic. Acesta este graficul din dreapta sus. <\/p>\n<p><\/p>\n<p>Graficul din col\u021bul st\u00e2ng inferior arat\u0103 cele mai lungi tranzac\u021bii. Vedem c\u0103 tranzac\u021biile se efectueaz\u0103 rapid. De asemenea, autovacuum-ul nu func\u021bioneaz\u0103 \u00eenc\u0103 aici, deoarece a fost un test de \u00eenceput. \u00cen continuare, acesta va func\u021biona \u0219i ne va fi util.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Erorile tipice \u00een aplica\u021bii care duc la bloat \u00een PostgreSQL. Andrei Salnikov\" src=\"\/wp-content\/uploads\/2020\/05\/9e9b46acd9a878ff70ca4a7850adff09.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Al doilea diapozitiv va fi \u00eentotdeauna dedicat tabelului testat. \u00cen aceast\u0103 situa\u021bie, actualiz\u0103m constant soldurile din conturile clientului. Vedem c\u0103 timpul mediu de r\u0103spuns pentru opera\u021bia de actualizare este destul de bun, mai pu\u021bin de o milisecund\u0103. Observ\u0103m c\u0103 resursele procesorului (acesta este graficul din col\u021bul drept superior) sunt consumate, de asemenea, uniform \u0219i \u00eentr-o m\u0103sur\u0103 destul de mic\u0103. <\/p>\n<p><\/p>\n<p>Graficul din col\u021bul drept inferior arat\u0103 c\u00e2t\u0103 memorie opera\u021bional\u0103 \u0219i de disc analiz\u0103m pentru a g\u0103si linia dorit\u0103 \u00eenainte de a o actualiza. Num\u0103rul de opera\u021bii pe tabel este de 2000 pe secund\u0103, a\u0219a cum am men\u021bionat la \u00eenceput. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Erorile tipice \u00een aplica\u021bii care duc la bloat \u00een PostgreSQL. Andrei Salnikov\" src=\"\/wp-content\/uploads\/2020\/05\/84760d52716209b8dcfffb462c67a8e1.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>\u0218i acum avem o tragedie. Dintr-un anumit motiv, apare o tranzac\u021bie lung\u0103 uitat\u0103. Cauzele sunt, de obicei, banale: <\/p>\n<p><\/p>\n<ul>\n<li>Una dintre cele mai frecvente este aceea c\u0103 am \u00eenceput s\u0103 apel\u0103m la un serviciu extern \u00een codul aplica\u021biei. Iar acest serviciu nu ne r\u0103spunde. Adic\u0103, am deschis o tranzac\u021bie, am f\u0103cut o modificare \u00een baz\u0103 \u0219i am plecat din aplica\u021bie s\u0103 citim emailurile sau s\u0103 ne ocup\u0103m de un alt serviciu din cadrul infrastructurii noastre, iar acesta, dintr-un motiv oarecare, nu ne r\u0103spunde. \u0218i sesiunea noastr\u0103 a r\u0103mas suspendat\u0103 cu o stare \u2013 necunoscut, c\u00e2nd se va rezolva.<\/li>\n<li>A doua situa\u021bie \u00een care, dintr-un anumit motiv, a ap\u0103rut un exception \u00een codul nostru. \u0218i nu am tratat \u00een exception \u00eenchiderea tranzac\u021biei. \u0218i astfel am ob\u021binut o sesiune suspendat\u0103 cu o tranzac\u021bie deschis\u0103. <\/li>\n<li>\u0218i \u00een final \u2013 acesta este \u0219i un caz destul de frecvent. Este vorba despre cod de proast\u0103 calitate. Unele framework-uri deschid o tranzac\u021bie. Ea r\u0103m\u00e2ne suspendat\u0103 \u0219i s-ar putea s\u0103 nu \u0219ti\u021bi \u00een aplica\u021bie c\u0103 aceasta este suspendat\u0103. <\/li>\n<\/ul>\n<p><\/p>\n<p>La ce duc astfel de lucruri? <\/p>\n<p><\/p>\n<p>La faptul c\u0103 tabelele \u0219i indec\u0219ii \u00eencep s\u0103 se umfle rapid. Acesta este efectul bloat. Pentru baza de date, aceasta se va traduce printr-o cre\u0219tere brusc\u0103 a timpului de r\u0103spuns al bazei de date, o cre\u0219tere a \u00eenc\u0103rc\u0103rii serverului de baze de date. \u0218i, ca rezultat, aplica\u021bia va suferi. Deoarece, dac\u0103 \u00een cod foloseai 10 milisecunde pentru o cerere \u00een baz\u0103, 10 milisecunde pentru logica ta, atunci func\u021bia ta se executa \u00een 20 milisecunde. Iar acum situa\u021bia ta va fi cu totul nepl\u0103cut\u0103. <\/p>\n<p><\/p>\n<p>\u0218i s\u0103 vedem ce se \u00eent\u00e2mpl\u0103. Grafica din col\u021bul st\u00e2ng inferior arat\u0103 c\u0103 avem o tranzac\u021bie lung\u0103 \u0219i prelungit\u0103. \u0218i dac\u0103 ne uit\u0103m la grafica din col\u021bul st\u00e2ng superior, vedem c\u0103 dimensiunea tabelului de la dou\u0103 megabytes a s\u0103rit brusc la 300 megabytes. \u00cen acela\u0219i timp, cantitatea de date din tabel nu s-a schimbat, adic\u0103 acolo este o cantitate destul de mare de de\u0219euri.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Erorile tipice \u00een aplica\u021bii care duc la bloat \u00een PostgreSQL. Andrei Salnikov\" src=\"\/wp-content\/uploads\/2020\/05\/b1947f6487e440a770a1251a955e62d2.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Situa\u021bia general\u0103 \u00een ceea ce prive\u0219te timpul mediu de r\u0103spuns al serverului s-a schimbat \u0219i ea cu c\u00e2teva ordine de magnitudine. Adic\u0103, toate cererile c\u0103tre server au \u00eenceput s\u0103 scad\u0103 drastic. \u00cen acela\u0219i timp, s-au activat procesele interne Postgres \u00een persoana autovacuum-ului, care \u00eencearc\u0103 s\u0103 fac\u0103 ceva \u0219i consum\u0103 resurse.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Erorile tipice \u00een aplica\u021bii care duc la bloat \u00een PostgreSQL. Andrei Salnikov\" src=\"\/wp-content\/uploads\/2020\/05\/8e91f035d1dd04e72e842d714cc611a5.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Ce se \u00eent\u00e2mpl\u0103 cu tabelul nostru? Acelasi lucru. Timpul mediu de r\u0103spuns pentru tabelul nostru a s\u0103rit cu c\u00e2teva ordine de magnitudine \u00een sus. Dac\u0103 ne referim la resursele consumate, vedem c\u0103 \u00eenc\u0103rc\u0103tura pe procesor a crescut foarte mult. Aceasta este grafica din col\u021bul dreapta sus. Aceasta a crescut deoarece procesorul trebuie s\u0103 caute \u00eentr-o mul\u021bime de linii inutile \u00een c\u0103utarea uneia necesare. Aceasta este grafica din col\u021bul dreapta inferior. \u0218i ca rezultat \u2013 num\u0103rul de apeluri pe secund\u0103 a \u00eenceput s\u0103 scad\u0103 drastic, deoarece baza nu reu\u0219e\u0219te s\u0103 proceseze aceea\u0219i cantitate de cereri. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Erorile tipice \u00een aplica\u021bii care duc la bloat \u00een PostgreSQL. Andrei Salnikov\" src=\"\/wp-content\/uploads\/2020\/05\/424685ce852bc5f3ef77151f8d3d7289.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Trebuie s\u0103 revenim la normalitate. Ne conect\u0103m la internet \u0219i afl\u0103m c\u0103 tranzac\u021biile lungi duc la probleme. G\u0103sim \u0219i elimin\u0103m aceast\u0103 tranzac\u021bie. \u0218i totul revine la normal. Totul func\u021bioneaz\u0103 cum trebuie. <\/p>\n<p><\/p>\n<p>Ne-am lini\u0219tit, dar dup\u0103 un timp \u00eencepem s\u0103 observ\u0103m c\u0103 aplica\u021bia nu func\u021bioneaz\u0103 la fel ca \u00eenainte de incident. Cererile sunt totu\u0219i procesate mai lent, \u0219i anume semnificativ mai lent. Cu 1,5-2 ori mai lent, \u00een cazul meu. \u00cenc\u0103rc\u0103tura pe server este, de asemenea, mai mare dec\u00e2t era \u00eenainte de incident. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Erorile tipice \u00een aplica\u021bii care duc la bloat \u00een PostgreSQL. Andrei Salnikov\" src=\"\/wp-content\/uploads\/2020\/05\/ee3037719a31f8d18fc42745716c4da5.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>\u0218i \u00eentrebarea este: \u201eCe se \u00eent\u00e2mpl\u0103 cu baza de date \u00een acel moment?\u201d. Iar cu baza se \u00eent\u00e2mpl\u0103 urm\u0103toarea situa\u021bie. \u00cen grafica tranzac\u021biilor vede\u021bi c\u0103 aceasta s-a oprit \u0219i acolo chiar nu exist\u0103 tranzac\u021bii lungi. Dar dimensiunile tabelului \u00een timpul incidentei au crescut fatal. \u0218i de atunci nu s-au mic\u0219orat. Timpul mediu pe baza s-a stabilizat. \u0218i r\u0103spunsurile par s\u0103 fie adecvate cu o vitez\u0103 acceptabil\u0103 pentru noi. Autovacuum-ul a devenit mai activ \u0219i a \u00eenceput s\u0103 fac\u0103 ceva cu tabelul, deoarece trebuie s\u0103 proceseze o cantitate mai mare de date. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Erorile tipice \u00een aplica\u021bii care duc la bloat \u00een PostgreSQL. Andrei Salnikov\" src=\"\/wp-content\/uploads\/2020\/05\/f6205242c4024dc3ed4cade5844dbf76.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Referitor la tabelul testat cu conturile, unde schimb\u0103m soldurile: timpul de r\u0103spuns la cerere pare s\u0103 fi revenit la normal. Dar de fapt, este de o dat\u0103 \u0219i jum\u0103tate mai mare.<\/p>\n<p><\/p>\n<p>\u0218i \u00een ceea ce prive\u0219te sarcina pe procesor, vedem c\u0103 aceasta nu a revenit la nivelul dorit p\u00e2n\u0103 la accident. Iar cauzele sunt tocmai \u00een graficul din col\u021bul din dreapta jos. Se observ\u0103 c\u0103 acolo se face o verificare a unui anumit num\u0103r de \u00eenregistr\u0103ri. Adic\u0103, pentru a g\u0103si linia dorit\u0103, consum\u0103m resursele serverului bazei de date c\u0103ut\u00e2nd date inutile. Num\u0103rul de tranzac\u021bii pe secund\u0103 s-a stabilizat. <\/p>\n<p><\/p>\n<p>\u00cen general, este bine, dar situa\u021bia este mai rea dec\u00e2t \u00eenainte. A existat o degradare evident\u0103 a bazei de date ca rezultat al aplica\u021biei noastre care interac\u021bioneaz\u0103 cu aceast\u0103 baz\u0103 de date. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Erorile tipice \u00een aplica\u021bii care duc la bloat \u00een PostgreSQL. Andrei Salnikov\" src=\"\/wp-content\/uploads\/2020\/05\/0dfc9cd453fd84bc639ffd99cf189fd2.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>\u0218i pentru a \u00een\u021belege ce se \u00eent\u00e2mpl\u0103 acolo, dac\u0103 nu a\u021bi fost la prezentarea anterioar\u0103, acum o s\u0103 facem o mic\u0103 teorie. Teoria despre procesul intern. De ce este necesar autovacuumul \u0219i ce rol joac\u0103?<\/p>\n<p><\/p>\n<p>Pe scurt, pentru a \u00een\u021belege. La un moment dat, avem un tabel. \u00cen tabel avem \u00eenregistr\u0103ri. Aceste \u00eenregistr\u0103ri pot fi active, vii, relevante pentru noi acum. \u00cen imagine, acestea sunt marcate cu verde. \u0218i exist\u0103 \u00eenregistr\u0103ri moarte, care au fost deja procesate, au fost actualizate, iar pentru ele au ap\u0103rut noi \u00eenregistr\u0103ri. Acestea sunt marcate ca fiind deja nesemnificative pentru baza de date. \u00cens\u0103 ele r\u0103m\u00e2n \u00een tabel din cauza particularit\u0103\u021bilor Postgres.<\/p>\n<p><\/p>\n<p>De ce este necesar autovacuumul? Autovacuumul la un moment dat vine, se adreseaz\u0103 bazei de date \u0219i o \u00eentreab\u0103: \u201eTe rog, d\u0103-mi id-ul celei mai vechi tranzac\u021bii care este deschis\u0103 \u00een acest moment \u00een baza de date\u201d. Baza de date returneaz\u0103 acest id. Iar autovacuumul, baz\u00e2ndu-se pe el, parcurge \u00eenregistr\u0103rile din tabel. \u0218i dac\u0103 observ\u0103 c\u0103 unele \u00eenregistr\u0103ri au fost modificate de tranzac\u021bii mult mai vechi, atunci el are dreptul s\u0103 le marcheze ca \u00eenregistr\u0103ri pe care le putem reutiliza \u00een viitor, scriind date noi \u00een ele. Acesta este un proces \u00een fundal.<\/p>\n<p><\/p>\n<p>\u00centre timp, continu\u0103m s\u0103 lucr\u0103m cu baza de date, continu\u0103m s\u0103 facem modific\u0103ri \u00een tabel. \u0218i pentru acele \u00eenregistr\u0103ri pe care le putem reutiliza, scriem date noi. Astfel, avem un ciclu, adic\u0103 tot timpul apar \u00eenregistr\u0103ri moarte vechi, iar \u00een locul lor scriem \u00eenregistr\u0103ri noi de care avem nevoie. \u0218i aceasta este o stare normal\u0103 pentru func\u021bionarea PostgreSQL.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Erorile tipice \u00een aplica\u021bii care duc la bloat \u00een PostgreSQL. Andrei Salnikov\" src=\"\/wp-content\/uploads\/2020\/05\/98dd4451a7ca5f418775f72822c2840c.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Ce s-a \u00eent\u00e2mplat \u00een timpul accidentului? Cum s-a desf\u0103\u0219urat acest proces acolo?<\/p>\n<p><\/p>\n<p>Aveam o tabel\u0103 \u00eentr-o anumit\u0103 stare, cu unele linii active, altele inactivate. A venit autovacuumul. A \u00eentrebat baza de date care este cea mai veche tranzac\u021bie, care este ID-ul ei. A ob\u021binut acest ID, care poate fi cu multe ore \u00een urm\u0103 sau poate fi cu zece minute \u00een urm\u0103. Acest lucru depinde de c\u00e2t de mare este sarcina pe baza de date. \u0218i a \u00eenceput s\u0103 caute liniile pe care le poate marca ca reutilizabile. \u0218i nu a g\u0103sit astfel de linii \u00een tabela noastr\u0103. <\/p>\n<p><\/p>\n<p>Dar \u00een acela\u0219i timp continu\u0103m s\u0103 lucr\u0103m cu tabela. Facem ceva \u00een ea, actualiz\u0103m, schimb\u0103m datele. Ce poate face baza de date \u00een acel moment? Nu \u00eei r\u0103m\u00e2ne altceva de f\u0103cut dec\u00e2t s\u0103 adauge linii noi la sf\u00e2r\u0219itul tabelului existent. Astfel, dimensiunea tabelului nostru \u00eencepe s\u0103 se umfle. <\/p>\n<p><\/p>\n<p>De fapt, avem nevoie de linii verzi pentru a lucra. Dar \u00een timpul unei astfel de probleme, ajungem la concluzia c\u0103 procentajul liniilor verzi este extrem de sc\u0103zut \u00een \u00eentreaga mas\u0103 a tabelului. <\/p>\n<p><\/p>\n<p>C\u00e2nd execut\u0103m o interogare, baza de date trebuie s\u0103 parcurg\u0103 toate liniile: at\u00e2t cele ro\u0219ii, c\u00e2t \u0219i cele verzi, pentru a g\u0103si linia dorit\u0103. Efectul umfl\u0103rii tabelului cu date inutile se nume\u0219te \u201ebloat\u201d, care consum\u0103 \u0219i spa\u021biul nostru pe disk. Aminti\u021bi-v\u0103, era 2 MB, a devenit 300 MB? Acum schimba\u021bi megabi\u021bii cu gigabi\u021bi, \u0219i ve\u021bi r\u0103m\u00e2ne destul de repede f\u0103r\u0103 resursele de disk.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Erorile tipice \u00een aplica\u021bii care duc la bloat \u00een PostgreSQL. Andrei Salnikov\" src=\"\/wp-content\/uploads\/2020\/05\/fe7cb6b5c99610744ebcfe5ad7235d1e.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Ce consecin\u021be pot exista pentru noi? <\/p>\n<p><\/p>\n<ul>\n<li>\u00cen exemplul meu, tabela \u0219i indexul au crescut de 150 de ori. La unii dintre clien\u021bii no\u0219tri au existat cazuri mai fatale, c\u00e2nd pur \u0219i simplu spa\u021biul pe disk a \u00eenceput s\u0103 se epuizeze. <\/li>\n<li>Dimensiunea tabelelor \u00een sine nu se va mic\u0219ora niciodat\u0103. Autovacuumul, \u00een unele cazuri, poate t\u0103ia o por\u021biune de la tabl\u0103, dac\u0103 acolo sunt doar linii inactivate. Dar, deoarece are loc o rota\u021bie constant\u0103, o linie verde poate r\u0103m\u00e2ne suspendat\u0103 la sf\u00e2r\u0219it \u0219i nu se va actualiza, \u00een timp ce toate celelalte vor fi scrise undeva la \u00eenceputul tabelului. Dar este un eveniment at\u00e2t de improbabil, \u00eenc\u00e2t tabela dvs. nu se va mic\u0219ora de la sine, deci nu ar trebui s\u0103 spera\u021bi la asta. <\/li>\n<li>Baza de date trebuie s\u0103 scaneze toate liniile inutile. \u0218i astfel, cheltuim resursele de disk, consum\u0103m resursele procesorului \u0219i energia electric\u0103. <\/li>\n<li>\u0218i acest lucru afecteaz\u0103 direct aplica\u021bia noastr\u0103, deoarece, dac\u0103 la \u00eenceput cheltuiam 10 milisecunde pentru o cerere, 10 milisecunde pentru codul nostru, \u00een timpul avariei am \u00eenceput s\u0103 cheltuim o secund\u0103 pentru cerere \u0219i 10 milisecunde pentru cod, adic\u0103 performan\u021ba aplica\u021biei a sc\u0103zut cu un ordin de magnitudine. Iar c\u00e2nd s-a rezolvat avaria, am \u00eenceput s\u0103 cheltuim 20 de milisecunde pentru cerere, 10 milisecunde pentru cod. Asta \u00eenseamn\u0103 c\u0103 am r\u0103mas totu\u0219i cu o sc\u0103dere de un \u0219i jum\u0103tate \u00een performan\u021b\u0103. \u0218i totul din cauza unei singure tranzac\u021bii care a fost suspendat\u0103, posibil din vina noastr\u0103. <\/li>\n<li>\u0218i \u00eentrebarea este: \u201eCum putem reveni la normal?\u201d, astfel \u00eenc\u00e2t totul s\u0103 func\u021bioneze bine \u0219i cererile s\u0103 fie la fel de rapide ca \u00eenainte de avarie. <\/li>\n<\/ul>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Erorile tipice \u00een aplica\u021bii care duc la bloat \u00een PostgreSQL. Andrei Salnikov\" src=\"\/wp-content\/uploads\/2020\/05\/1bf46e8cd9b28ca2862f978f2ca85819.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Pentru aceasta exist\u0103 un anumit ciclu de lucr\u0103ri care se desf\u0103\u0219oar\u0103. <\/p>\n<p><\/p>\n<p>Mai \u00eent\u00e2i, trebuie s\u0103 g\u0103sim tabelele problematice, care s-au umflat. \u00cen\u021belegem c\u0103, \u00een func\u021bie de anumite tabele, \u00eenregistr\u0103rile se fac mai activ, iar \u00een altele mai pu\u021bin activ. \u0218i pentru aceasta se folose\u0219te extensia <noindex><a rel=\"nofollow\" href=\"https:\/\/www.postgresql.org\/docs\/current\/pgstattuple.html\">pgstattuple<\/a><\/noindex>. Instal\u00e2nd aceast\u0103 extensie, pute\u021bi scrie cereri care v\u0103 ajut\u0103 s\u0103 g\u0103si\u021bi tabelele care s-au umflat considerabil. <\/p>\n<p><\/p>\n<p>Dup\u0103 ce a\u021bi g\u0103sit aceste tabele, trebuie s\u0103 le comprima\u021bi. Pentru aceasta existen\u021bia deja instrumente. \u00cen compania noastr\u0103 folosim trei instrumente. Primul \u2013 VACUUM FULL \u00eencorporat. Este brutal, sever \u0219i necru\u021b\u0103tor, dar uneori este foarte util. <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/reorg\/pg_repack\">Pg_repack<\/a><\/noindex> \u0219i <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/dataegret\/pgcompacttable\">pgcompacttable<\/a><\/noindex> \u2013 sunt utilitare externe pentru comprimarea tabelelor. \u0218i se comport\u0103 mai delicat cu baza de date. <\/p>\n<p><\/p>\n<p>Acestea sunt folosite \u00een func\u021bie de ceea ce v\u0103 este mai convenabil. Dar despre asta voi vorbi la final. Principalul lucru este c\u0103 exist\u0103 trei instrumente. Avem de unde alege. <\/p>\n<p><\/p>\n<p>Dup\u0103 ce am corectat totul, am confirmat c\u0103 totul a devenit bine, trebuie s\u0103 \u0219tim cum s\u0103 prevenim aceast\u0103 situa\u021bie \u00een viitor:<\/p>\n<p><\/p>\n<ul>\n<li>Se previne destul de u\u0219or. Trebuie s\u0103 monitoriz\u0103m durata sesiunilor pe serverul Master. <strong>Sesiunile \u00een stare de idle in transaction sunt deosebit de periculoase.<\/strong>Acestea sunt cele care au deschis o tranzac\u021bie, au f\u0103cut ceva \u0219i au plecat sau pur \u0219i simplu au r\u0103mas suspendate, pierdute \u00een cod. <\/li>\n<li>\u0218i pentru voi, ca dezvoltatori, este important s\u0103 testa\u021bi codul \u00een momentul apari\u021biei acestor situa\u021bii. Nu este greu de realizat. Aceasta va fi o verificare util\u0103. Vei evita o mul\u021bime de probleme \u201ecopil\u0103re\u0219ti\u201d legate de tranzac\u021bii lungi. <\/li>\n<\/ul>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Erorile tipice \u00een aplica\u021bii care duc la bloat \u00een PostgreSQL. Andrei Salnikov\" src=\"\/wp-content\/uploads\/2020\/05\/d55465d96c4018db733954867d23aaba.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>\u00cen aceste grafice, doream s\u0103 v\u0103 ar\u0103t cum s-a modificat tabelul \u0219i comportamentul bazei de date dup\u0103 ce am aplicat VACUUM FULL pe tabel. Acesta nu este un mediu de produc\u021bie.<\/p>\n<p><\/p>\n<p>Dimensiunea tabelului a revenit imediat la o stare normal\u0103 de lucru, de c\u00e2\u021biva megabytes. Timpul mediu de r\u0103spuns al serverului nu a fost afectat semnificativ. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Erorile tipice \u00een aplica\u021bii care duc la bloat \u00een PostgreSQL. Andrei Salnikov\" src=\"\/wp-content\/uploads\/2020\/05\/cbb07ad24dba899395223d1ca25e438e.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Dar, \u00een cazul tabelului nostru testat, unde am actualizat soldurile conturilor, vedem c\u0103 timpul mediu de r\u0103spuns pentru interog\u0103rile de actualizare a datelor din tabel a sc\u0103zut la nivelul pre-incident. Resursele consumate de procesor pentru executarea acestei interog\u0103ri au sc\u0103zut, de asemenea, la nivelul pre-incident. Iar graficul din col\u021bul din dreapta jos arat\u0103 c\u0103 acum g\u0103sim exact linia de care avem nevoie imediat, f\u0103r\u0103 a parcurge o mul\u021bime de linii moarte care existau \u00eenainte de comprimarea tabelului. Timpul mediu al interog\u0103rilor a r\u0103mas aproximativ pe acela\u0219i nivel. Dar aici am o eroare de m\u0103surare din partea hardware-ului meu.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Erorile tipice \u00een aplica\u021bii care duc la bloat \u00een PostgreSQL. Andrei Salnikov\" src=\"\/wp-content\/uploads\/2020\/05\/c1d90c5442e02fce209dc40e048a8ca2.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Aici se \u00eencheie prima poveste. Este cea mai comun\u0103. Se \u00eent\u00e2mpl\u0103 tuturor, indiferent de experien\u021ba clientului sau de c\u00e2t de califica\u021bi sunt programatorii. Mai devreme sau mai t\u00e2rziu, acest lucru se \u00eent\u00e2mpl\u0103. <\/p>\n<p><\/p>\n<p>A doua poveste, \u00een care distribuim sarcina \u0219i optimiz\u0103m resursele serverului.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Erorile tipice \u00een aplica\u021bii care duc la bloat \u00een PostgreSQL. Andrei Salnikov\" src=\"\/wp-content\/uploads\/2020\/05\/cda421c554d1329107ddc935045cc1b9.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<ul>\n<li>Am crescut \u0219i am devenit juc\u0103tori serio\u0219i. \u00cen\u021belegem c\u0103 avem o replic\u0103 \u0219i ar fi bine s\u0103 echilibr\u0103m sarcina: scriem pe Master \u0219i citim de pe replic\u0103. Aceast\u0103 situa\u021bie apare de obicei c\u00e2nd dorim s\u0103 preg\u0103tim rapoarte sau ETL. Iar afacerea este foarte \u00eenc\u00e2ntat\u0103. \u00ce\u0219i dore\u0219te rapoarte diverse, cu multe analize complexe. <\/li>\n<li>Rapoartele sunt de lung\u0103 durat\u0103, pentru c\u0103 analiza complex\u0103 nu poate fi realizat\u0103 \u00een milisecunde. Noi, ca b\u0103ie\u021bi harnici, scriem cod. Facem \u00een aplica\u021bie inser\u021bii, adic\u0103 \u00eenregistrarea se face pe Master, iar rapoartele sunt executate pe replic\u0103. <\/li>\n<li>Distribuim sarcina. <\/li>\n<li>Totul func\u021bioneaz\u0103 perfect. Suntem grozavi. <\/li>\n<\/ul>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Erorile tipice \u00een aplica\u021bii care duc la bloat \u00een PostgreSQL. Andrei Salnikov\" src=\"\/wp-content\/uploads\/2020\/05\/e94c8c492197a5015ac8aae79389a4c2.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>\u0218i cum arat\u0103 aceast\u0103 situa\u021bie? \u00cen mod specific, \u00een aceste grafice am ad\u0103ugat, de asemenea, durata tranzac\u021biilor de pe replic\u0103. Toate celelalte grafice se refer\u0103 doar la serverul Master. <\/p>\n<p><\/p>\n<p>Tabela cu rapoartele de p\u00e2n\u0103 acum a crescut. Au devenit mai multe. Vedem c\u0103 timpul mediu de r\u0103spuns al serverului este stabil. Observ\u0103m c\u0103 pe replic\u0103 avem o tranzac\u021bie lung\u0103 care dureaz\u0103 2 ore. Vedem func\u021bionarea lin\u0103 a autovacuum-ului, care proceseaz\u0103 liniile moarte. Totul este \u00een regul\u0103. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Erorile tipice \u00een aplica\u021bii care duc la bloat \u00een PostgreSQL. Andrei Salnikov\" src=\"\/wp-content\/uploads\/2020\/05\/2da8acf098d12d6f146ab9b9dcb54b81.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>\u00cen ceea ce prive\u0219te tabela testat\u0103, continu\u0103m s\u0103 actualiz\u0103m soldurile din conturi. \u0218i avem un timp de r\u0103spuns stabil pentru cereri, consum stabil de resurse. Totul este bine. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Erorile tipice \u00een aplica\u021bii care duc la bloat \u00een PostgreSQL. Andrei Salnikov\" src=\"\/wp-content\/uploads\/2020\/05\/3621ef723017bac6fb635caf0a5f4de6.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Totul este bine p\u00e2n\u0103 \u00een momentul \u00een care aceste rapoarte \u00eencep s\u0103 se confrunte cu conflicte \u00een replicare. \u0218i se \u00eent\u00e2mpl\u0103 la intervale regulate. <\/p>\n<p><\/p>\n<p>Intr\u0103m pe internet \u0219i \u00eencepem s\u0103 citim de ce se \u00eent\u00e2mpl\u0103 acest lucru. \u0218i g\u0103sim o solu\u021bie. <\/p>\n<p><\/p>\n<p>Prima solu\u021bie este s\u0103 cre\u0219tem \u00eent\u00e2rzierea replic\u0103rii. \u0218tim c\u0103 raportul nostru func\u021bioneaz\u0103 timp de 3 ore. Stabilim \u00eent\u00e2rzierea replic\u0103rii - 3 ore. Pornim totul, dar avem \u00een continuare probleme cu faptul c\u0103 rapoartele uneori sunt afectate. <\/p>\n<p><\/p>\n<p>Vrem ca totul s\u0103 fie perfect. C\u0103ut\u0103m mai departe. \u0218i g\u0103sim pe internet o setare interesant\u0103 - hot_standby_feedback. O activ\u0103m. Hot_standby_feedback ne permite s\u0103 am\u00e2n\u0103m func\u021bionarea autovacuum-ului pe Master. Astfel, ne elimin\u0103m complet conflictele de replicare. \u0218i totul func\u021bioneaz\u0103 bine cu rapoartele.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Erorile tipice \u00een aplica\u021bii care duc la bloat \u00een PostgreSQL. Andrei Salnikov\" src=\"\/wp-content\/uploads\/2020\/05\/ee3c315168bdd3f392d2e8a1c5861004.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Ce se \u00eent\u00e2mpl\u0103 \u00een aceast\u0103 perioad\u0103 cu serverul Master? Cu serverul Master, avem o problem\u0103 grav\u0103. Acum observ\u0103m graficele, c\u00e2nd am activat aceste dou\u0103 set\u0103ri. \u0218i vedem c\u0103 sesiunea de pe replic\u0103 a \u00eenceput s\u0103 influen\u021beze situa\u021bia pe serverul Master. Aceasta chiar influen\u021beaz\u0103, deoarece a suspendat autovacuum-ul, care cur\u0103\u021b\u0103 liniile moarte. Dimensiunea tabelei a s\u0103rit din nou \u00een aer. Timpul mediu de execu\u021bie a cererilor \u00een \u00eentreaga baz\u0103 de date a crescut, de asemenea. Autovacuum-urile au \u00eenceput s\u0103 fie mai solicitante. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Erorile tipice \u00een aplica\u021bii care duc la bloat \u00een PostgreSQL. Andrei Salnikov\" src=\"\/wp-content\/uploads\/2020\/05\/980611dcce8b189dc50f422ffd3d2d72.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>\u00cen specific pentru tabela noastr\u0103, vedem c\u0103 actualizarea datelor a crescut foarte mult. Consumul de resurse CPU a crescut de asemenea dramatic. Revenim s\u0103 vedem un num\u0103r mare de linii moarte inutile. \u0218i timpul de r\u0103spuns pentru aceast\u0103 tabel\u0103, num\u0103rul de tranzac\u021bii a sc\u0103zut. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Erorile tipice \u00een aplica\u021bii care duc la bloat \u00een PostgreSQL. Andrei Salnikov\" src=\"\/wp-content\/uploads\/2020\/05\/a648fd313a5dccf45f0056dc13c54263.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Cum ar ar\u0103ta dac\u0103 nu \u0219tim despre ce am vorbit p\u00e2n\u0103 acum?<\/p>\n<p><\/p>\n<ul>\n<li>\u00cencepem s\u0103 c\u0103ut\u0103m problemele. Dac\u0103 ne-am confruntat cu probleme \u00een prima parte, \u0219tim c\u0103 aceasta ar putea fi din cauza unei tranzac\u021bii lungi \u0219i ne \u00eendrept\u0103m spre Master. Problema este la noi pe Master. Timpul de r\u0103spuns este mare. Se supra\u00eenc\u0103lze\u0219te, are Load Average aproape de o sut\u0103. <\/li>\n<li>Solicit\u0103rile sunt \u00eent\u00e2rziate, dar nu vedem tranzac\u021bii lungi acolo. \u0218i nu \u00een\u021belegem de ce. Nu \u0219tim unde s\u0103 c\u0103ut\u0103m. <\/li>\n<li>Verific\u0103m echipamentul serverului. Poate c\u0103 raid-ul s-a defectat. Poate c\u0103 a ars o memorie. Orice s-ar putea \u00eent\u00e2mpla. Dar nu, serverele sunt noi, totul func\u021bioneaz\u0103 perfect. <\/li>\n<li>Toat\u0103 lumea alearg\u0103: administratori, dezvoltatori \u0219i directorul. Nimic nu ajut\u0103. <\/li>\n<li>\u0218i, \u00eentr-un anumit moment, totul \u00eencepe s\u0103 se corecteze de la sine. <\/li>\n<\/ul>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Erorile tipice \u00een aplica\u021bii care duc la bloat \u00een PostgreSQL. Andrei Salnikov\" src=\"\/wp-content\/uploads\/2020\/05\/7d4f6417bc5cb3cec33679d843c6661d.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Pe replica noastr\u0103, la acel moment, o solicitare a fost procesat\u0103 \u0219i a plecat. Am primit un raport. Afacerea este \u00een continuare mul\u021bumit\u0103. A\u0219a cum vedem, tabelul nostru a crescut din nou \u0219i nu se va mic\u0219ora. Pe graficul sesiunilor am l\u0103sat o bucat\u0103 din aceast\u0103 tranzac\u021bie lung\u0103 de pe replica, pentru a putea evalua c\u00e2t de mult timp dureaz\u0103 p\u00e2n\u0103 c\u00e2nd situa\u021bia se stabilizeaz\u0103. <\/p>\n<p><\/p>\n<p>Sesiunea a plecat. \u0218i doar dup\u0103 un timp serverul revine \u00eentr-o stare mai bun\u0103. Timpul mediu de r\u0103spuns al solicit\u0103rilor pe serverul Master revine la normal. Pentru c\u0103, \u00een sf\u00e2r\u0219it, autovacuum a primit oportunitatea de a cur\u0103\u021ba, de a marca aceste linii moarte. \u0218i a \u00eenceput s\u0103-\u0219i fac\u0103 treaba. \u0218i cu c\u00e2t o face mai repede, cu at\u00e2t mai repede ne vom pune \u00een ordine.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Erorile tipice \u00een aplica\u021bii care duc la bloat \u00een PostgreSQL. Andrei Salnikov\" src=\"\/wp-content\/uploads\/2020\/05\/547d195e08de1566da818150a47218eb.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Pe tabelul testat, unde actualiz\u0103m soldurile conturilor, vedem exact aceea\u0219i imagine. Timpul mediu de actualizare a contului se normalizeaz\u0103 treptat. Resursele consumate de procesor, de asemenea, scad. \u0218i num\u0103rul de tranzac\u021bii pe secund\u0103 revine la normal. Dar din nou, nu la normalitatea pe care o aveam \u00eenainte de accident. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Erorile tipice \u00een aplica\u021bii care duc la bloat \u00een PostgreSQL. Andrei Salnikov\" src=\"\/wp-content\/uploads\/2020\/05\/29372a5e9124690931485a7aea65befc.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>\u00cen orice caz, suferim o sc\u0103dere a performan\u021bei, la fel ca \u0219i \u00een primul caz, cu un procent de unu comma cinci p\u00e2n\u0103 la dou\u0103 ori, sau chiar mai mult. <\/p>\n<p><\/p>\n<p>Se pare c\u0103 am f\u0103cut totul corect. Am distribuit \u00eenc\u0103rc\u0103tura. Echipamentul nu este inactiv. Am divizat solicit\u0103rile \u00een mod judicios, dar totu\u0219i a ie\u0219it totul prost. <\/p>\n<p><\/p>\n<ul>\n<li>Nu activa\u021bi hot_standby_feedback? Da, nu se recomand\u0103 activarea acestuia f\u0103r\u0103 motive serioase. Acest control afecteaz\u0103 direct serverul principal \u0219i suspend\u0103 func\u021bionarea autovacuum-ului de acolo. Activ\u00e2ndu-l pe o replic\u0103 \u0219i uit\u00e2nd de el, pute\u021bi distruge serverul principal \u0219i ve\u021bi avea mari probleme cu aplica\u021bia. <\/li>\n<li>Cre\u0219terea max_standby_streaming_delay? Da, pentru rapoarte - a\u0219a este. Dac\u0103 ave\u021bi un raport de trei ore \u0219i nu dori\u021bi s\u0103 se blocheze din cauza conflictelor de replicare, atunci pur \u0219i simplu cre\u0219te\u021bi \u00eent\u00e2rziera. Un raport de lung\u0103 durat\u0103 nu va necesita date care au ajuns \u00een baza de date chiar acum. Dac\u0103 raportul este de trei ore, \u00eenseamn\u0103 c\u0103 \u00eel rula\u021bi pe o perioad\u0103 mai veche de date. Deci, fie c\u0103 este o \u00eent\u00e2rziere de trei ore, fie de \u0219ase ore - nu va conta, dar ve\u021bi primi rapoarte constant \u0219i nu ve\u021bi avea probleme cu c\u0103derile acestora. <\/li>\n<li>Desigur, trebuie s\u0103 monitoriz\u0103m sesiunile lungi pe replici, mai ales dac\u0103 a\u021bi decis s\u0103 activa\u021bi hot_standby_feedback pe replic\u0103. Pentru c\u0103 poate ap\u0103rea orice. A\u021bi dat aceast\u0103 replic\u0103 unui dezvoltator pentru a testa interog\u0103rile. Acesta a scris o interogare nebun\u0103. A activat-o \u0219i a plecat s\u0103 bea ceai, iar noi am ob\u021binut un server principal supra\u00eenc\u0103rcat. Sau am l\u0103sat s\u0103 intre o aplica\u021bie gre\u0219it\u0103. Situa\u021biile sunt variate. Sesiunile pe replici trebuie monitorizate la fel de atent ca cele de pe serverul principal. <\/li>\n<li>\u0218i dac\u0103 ave\u021bi interog\u0103ri rapide \u0219i lungi pe replici, \u00een acest caz, este mai bine s\u0103 le distribui\u021bi pentru a echilibra \u00eenc\u0103rc\u0103tura. Acesta este un link c\u0103tre streaming_delay. Pentru interog\u0103ri rapide, ave\u021bi o replic\u0103 cu o \u00eent\u00e2rziere mic\u0103 \u00een replicare. Pentru interog\u0103rile lungi de raport, ave\u021bi o replic\u0103 care poate \u00eent\u00e2rzia cu 6 ore sau chiar o zi. Aceasta este o situa\u021bie complet normal\u0103. <\/li>\n<\/ul>\n<p><\/p>\n<p>Elimin\u0103m consecin\u021bele tot prin aceea\u0219i metod\u0103:<\/p>\n<p><\/p>\n<ul>\n<li>G\u0103sim tabelele umflate.<\/li>\n<li>\u0218i le comprim\u0103m cu cel mai convenabil instrument care ne se potrive\u0219te. <\/li>\n<\/ul>\n<p><\/p>\n<p>Povestea a doua s-a \u00eencheiat aici. Trecem la povestea a treia. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Erorile tipice \u00een aplica\u021bii care duc la bloat \u00een PostgreSQL. Andrei Salnikov\" src=\"\/wp-content\/uploads\/2020\/05\/c8784e0be27883640cb8f6919a1c25e0.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>De asemenea, destul de obi\u0219nuit\u0103 pentru noi, \u00een care facem migrarea. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Erorile tipice \u00een aplica\u021bii care duc la bloat \u00een PostgreSQL. Andrei Salnikov\" src=\"\/wp-content\/uploads\/2020\/05\/a04b9cd88a0e7e8a3b960ef930eb2657.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<ul>\n<li>Orice produs software cre\u0219te. Cerin\u021bele la acesta se schimb\u0103. Vrem s\u0103 ne dezvolt\u0103m \u00een orice caz. \u0218i se \u00eent\u00e2mpl\u0103 uneori c\u0103 trebuie s\u0103 actualiz\u0103m datele din tabel, exact s\u0103 rul\u0103m un update \u00een cadrul migra\u021biei noastre pentru noua func\u021bionalitate pe care o implement\u0103m \u00een cadrul dezvolt\u0103rii noastre. <\/li>\n<li>Formatul vechi de date nu este satisf\u0103c\u0103tor. S\u0103 presupunem c\u0103 ne vom referi acum la a doua tabel\u0103, \u00een care am \u00eenregistr\u0103rile pentru aceste conturi. \u0218i, s\u0103 zicem c\u0103 acestea erau \u00een ruble, iar noi am decis s\u0103 cre\u0219tem precizia \u0219i s\u0103 lucr\u0103m \u00een copeici. \u0218i pentru asta trebuie s\u0103 facem o actualizare: c\u00e2mpul cu suma opera\u021biei s\u0103 fie \u00eenmul\u021bit cu o sut\u0103. <\/li>\n<li>\u00cen lumea modern\u0103, folosim instrumente automatizate pentru controlul versiunilor bazei de date. S\u0103 presupunem c\u0103 <noindex><a rel=\"nofollow\" href=\"https:\/\/www.liquibase.org\/\">Liquibase<\/a><\/noindex>. \u00cel configur\u0103m pentru migrarea noastr\u0103. O test\u0103m pe baza noastr\u0103 de teste. Totul este excelent. Actualizarea trece. Blocheaz\u0103 activitatea pentru o vreme, dar astfel ob\u021binem date actualizate. \u0218i putem lansa noul func\u021bional \u00een acest sens. Totul a fost testat, verificat. Totul este confirmat. <\/li>\n<li>Am realizat lucr\u0103ri planificate, am efectuat migrarea. <\/li>\n<\/ul>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Erorile tipice \u00een aplica\u021bii care duc la bloat \u00een PostgreSQL. Andrei Salnikov\" src=\"\/wp-content\/uploads\/2020\/05\/9e046583f7b1723fc1eaf61a03900918.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Iat\u0103 migrarea cu actualizarea prezentat\u0103 \u00een fa\u021ba dumneavoastr\u0103. Deoarece sunt \u00eenregistr\u0103ri pentru conturi, tabela avea 15 GB. \u0218i, deoarece actualiz\u0103m fiecare r\u00e2nd, am m\u0103rit tabela de dou\u0103 ori prin actualizare, pentru c\u0103 am rescris fiecare r\u00e2nd. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Erorile tipice \u00een aplica\u021bii care duc la bloat \u00een PostgreSQL. Andrei Salnikov\" src=\"\/wp-content\/uploads\/2020\/05\/06120c98ea43d0568045e71935c23592.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>\u00cen timpul migra\u021biei, nu am putut face nimic cu aceast\u0103 tabel\u0103, pentru c\u0103 toate cererile c\u0103tre ea au stat la coad\u0103 \u0219i au a\u0219teptat p\u00e2n\u0103 c\u00e2nd s-a \u00eencheiat aceast\u0103 actualizare. Dar aici vreau s\u0103 v\u0103 atrag aten\u021bia asupra cifrelor de pe axa vertical\u0103. Adic\u0103 avem un timp mediu de cerere \u00eenainte de migrare \u00een jur de 5 milisecunde \u0219i o \u00eenc\u0103rcare pe procesor, num\u0103rul opera\u021biunilor de blocare pentru citirea memoriei discurilor este mai mic dec\u00e2t 7,5. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Erorile tipice \u00een aplica\u021bii care duc la bloat \u00een PostgreSQL. Andrei Salnikov\" src=\"\/wp-content\/uploads\/2020\/05\/69a3ba4d1d0cec7d39284e09e9d3055b.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Am efectuat migrarea \u0219i am avut din nou probleme. <\/p>\n<p><\/p>\n<p>Migrarea a fost un succes, dar:<\/p>\n<p><\/p>\n<ul>\n<li>Func\u021bionalitatea veche a \u00eenceput s\u0103 fie mai lent\u0103. <\/li>\n<li>Tabela a crescut din nou \u00een dimensiuni. <\/li>\n<li>\u00cenc\u0103rcarea pe server a crescut din nou peste nivelul anterior. <\/li>\n<li>\u0218i, desigur, deocamdat\u0103 ne ocup\u0103m cu func\u021bionalitatea care a func\u021bionat bine, am \u00eembun\u0103t\u0103\u021bit-o pu\u021bin. <\/li>\n<\/ul>\n<p><\/p>\n<p>\u0218i acesta este din nou bloat, care ne stric\u0103 din nou via\u021ba. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Erorile tipice \u00een aplica\u021bii care duc la bloat \u00een PostgreSQL. Andrei Salnikov\" src=\"\/wp-content\/uploads\/2020\/05\/becd7cce3a1c8821c81c96257f41202b.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Aici demonstrez c\u0103 tabela, ca \u00een precedentele dou\u0103 cazuri, nu se va \u00eentoarce la dimensiunile anterioare. \u00cenc\u0103rcarea medie a serverului pare a fi adecvat\u0103. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Erorile tipice \u00een aplica\u021bii care duc la bloat \u00een PostgreSQL. Andrei Salnikov\" src=\"\/wp-content\/uploads\/2020\/05\/4d703a60d43a3460bc3782d49865b690.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Dac\u0103 ne uit\u0103m la tabela cu conturi, vom observa c\u0103 timpul mediu de solicitare a crescut de dou\u0103 ori pentru aceast\u0103 tabel\u0103. Sarcina pe procesor \u0219i num\u0103rul de r\u00e2nduri scanate \u00een memorie au s\u0103rit peste 7,5, \u00een timp ce erau sub aceasta. A crescut de dou\u0103 ori \u00een cazul procesoarelor \u0219i cu 1,5 ori \u00een cazul opera\u021biunilor pe blocuri, adic\u0103 am avut o degradare a performan\u021bei serverului. Ca urmare \u2013 o degradare a performan\u021bei aplica\u021biei noastre. Totu\u0219i, num\u0103rul apelurilor a r\u0103mas aproximativ la acela\u0219i nivel. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Erorile tipice \u00een aplica\u021bii care duc la bloat \u00een PostgreSQL. Andrei Salnikov\" src=\"\/wp-content\/uploads\/2020\/05\/80772afa0643b29f5314a2482c9dfe0d.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Aici este esen\u021bial s\u0103 \u00een\u021belegem cum s\u0103 facem corect aceste migra\u021bii. Iar acestea trebuie realizate. Facem destul de constant aceste migra\u021bii.<\/p>\n<p><\/p>\n<ul>\n<li>Astfel de migra\u021bii mari nu se fac automat. Ele trebuie s\u0103 fie \u00eentotdeauna controlate. <\/li>\n<li>Este necesar un control din partea unei persoane competente. Dac\u0103 ave\u021bi un DBA \u00een echip\u0103, l\u0103sa\u021bi-l pe acesta s\u0103 se ocupe de asta. Este treaba lui. Dac\u0103 nu, atunci cea mai experimentat\u0103 persoan\u0103 ar trebui s\u0103 se ocupe, cine \u0219tie cum s\u0103 lucreze cu bazele de date. <\/li>\n<li>Schema nou\u0103 a bazei de date, chiar \u0219i \u00een cazul \u00een care actualiz\u0103m o coloan\u0103, o preg\u0103tim \u00eentotdeauna \u00een etape, adic\u0103 cu mult \u00eenainte de a lansa noua versiune a aplica\u021biei:<\/li>\n<li>Se adaug\u0103 noi c\u00e2mpuri, \u00een care vom scrie datele actualizate. <\/li>\n<li>Transfer\u0103m datele din c\u00e2mpul vechi \u00een cel nou \u00een por\u021biuni mici. De ce facem asta? \u00cen primul r\u00e2nd, \u00eentotdeauna control\u0103m procesul acestui transfer. \u0218tim c\u0103 am transferat deja un anumit num\u0103r de loturi \u0219i ne mai r\u0103m\u00e2ne at\u00e2t. <\/li>\n<li>Un alt beneficiu este c\u0103 \u00eentre fiecare lot de acest tip, \u00eenchidem o tranzac\u021bie, deschidem una nou\u0103 \u0219i acest lucru \u00eei permite auto-vacuum-ului s\u0103 func\u021bioneze pe tabel\u0103, marc\u00e2nd r\u00e2ndurile moarte pentru reutilizare. <\/li>\n<li>Pentru r\u00e2ndurile care apar \u00een timpul func\u021bion\u0103rii aplica\u021biei (\u00eenc\u0103 avem aplica\u021bia veche \u00een func\u021biune) ad\u0103ug\u0103m un trigger care scrie noi valori \u00een c\u00e2mpurile noi. \u00cen cazul nostru \u2013 este multiplicarea cu o sut\u0103 a valorii vechi. <\/li>\n<li>Dac\u0103 suntem foarte \u00eenc\u0103p\u0103\u021b\u00e2na\u021bi \u0219i dorim acela\u0219i c\u00e2mp, la finalizarea tuturor migra\u021biilor \u0219i \u00eenainte de a lansa noua versiune a aplica\u021biei, pur \u0219i simplu redenumim c\u00e2mpurile. Pe cele vechi le denumim \u00eentr-un mod inventat, iar c\u00e2mpurile noi le redenumim pe cele vechi. <\/li>\n<li>\u0218i doar dup\u0103 aceea lans\u0103m noua versiune a aplica\u021biei. <\/li>\n<\/ul>\n<p><\/p>\n<p>\u00cen plus, nu vom ob\u021bine bloat \u0219i nu vom sc\u0103dea \u00een performan\u021b\u0103. <\/p>\n<p><\/p>\n<p>Aici s-a \u00eencheiat cea de-a treia poveste. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Erorile tipice \u00een aplica\u021bii care duc la bloat \u00een PostgreSQL. Andrei Salnikov\" src=\"\/wp-content\/uploads\/2020\/05\/2afab2906b5ccd30e4c8772248818057.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p><noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/dataegret\/pg-utils\/blob\/master\/sql\/table_bloat.sql\">https:\/\/github.com\/dataegret\/pg-utils\/blob\/master\/sql\/table_bloat.sql<\/a><\/noindex><\/p>\n<p><\/p>\n<p><noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/dataegret\/pg-utils\/blob\/master\/sql\/table_bloat_approx.sql\">https:\/\/github.com\/dataegret\/pg-utils\/blob\/master\/sql\/table_bloat_approx.sql<\/a><\/noindex><\/p>\n<p><\/p>\n<p>\u0218i acum s\u0103 vorbim pu\u021bin mai detaliat despre instrumentele pe care le-am men\u021bionat \u00een prima poveste. <\/p>\n<p><\/p>\n<p>\u00cenainte de a c\u0103uta bloat, trebuie s\u0103 instala\u021bi neap\u0103rat extensia <noindex><a rel=\"nofollow\" href=\"https:\/\/www.postgresql.org\/docs\/current\/pgstattuple.html\">pgstattuple<\/a><\/noindex>.<\/p>\n<p><\/p>\n<p>Pentru a nu fi nevoit s\u0103 inventa\u021bi interog\u0103ri, noi am scris deja aceste interog\u0103ri \u00een munca noastr\u0103. Le pute\u021bi folosi. Aici sunt prezentate dou\u0103 interog\u0103ri. <\/p>\n<p><\/p>\n<ul>\n<li>Prima dureaz\u0103 destul de mult, dar v\u0103 va ar\u0103ta valorile exacte ale bloat-ului din tabel. <\/li>\n<li>A doua func\u021bioneaz\u0103 mai repede \u0219i este foarte eficient\u0103 atunci c\u00e2nd trebuie s\u0103 evalua\u021bi rapid \u2013 exist\u0103 bloat sau nu \u00een tabel. De asemenea, trebuie s\u0103 \u00een\u021belege\u021bi c\u0103 bloat-ul \u00een tabela Postgres exist\u0103 \u00eentotdeauna. Aceasta este o caracteristic\u0103 a modelului s\u0103u MVCC. <\/li>\n<li>\u0218i 20% bloat este normal pentru tabele \u00een majoritatea cazurilor. Adic\u0103, nu trebuie s\u0103 v\u0103 face\u021bi griji \u0219i s\u0103 compresa\u021bi aceast\u0103 tabel\u0103. <\/li>\n<\/ul>\n<p><\/p>\n<p>Cum s\u0103 identific\u0103m tabelele care s-au umflat, am \u00een\u021beles, \u00een special atunci c\u00e2nd s-au umflat cu date inutile. <\/p>\n<p><\/p>\n<p>Acum despre cum s\u0103 corect\u0103m bloat-ul:<\/p>\n<p><\/p>\n<ul>\n<li>Dac\u0103 avem o tabel\u0103 mic\u0103 \u0219i discuri bune, adic\u0103 pentru o tabel\u0103 de p\u00e2n\u0103 la un gigabyte este perfect posibil s\u0103 folosim VACUUM FULL. Acesta va lua o blocare exclusiv\u0103 pe tabel pentru c\u00e2\u021biva secunde \u0219i asta e, dar va face totul rapid \u0219i eficient. Ce face VACUUM FULL? Ia o blocare exclusiv\u0103 pe tabel \u0219i scrie liniile active din tabelele vechi \u00een tabel\u0103 nou\u0103. \u0218i la final le schimb\u0103 \u00eentre ele. Dosarele vechi sunt eliminate, iar cele noi sunt \u00eenlocuite. Dar pe durata execu\u021biei sale, ia o blocare exclusiv\u0103 pe tabel. Asta \u00eenseamn\u0103 c\u0103 nu ve\u021bi putea face nimic cu acea tabel\u0103: nu ve\u021bi putea scrie \u00een ea, nu ve\u021bi putea citi din ea, nu ve\u021bi putea modifica. \u0218i VACUUM FULL necesit\u0103 spa\u021biu suplimentar pe disc pentru a scrie datele.<\/li>\n<li>Urm\u0103torul instrument <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/reorg\/pg_repack\">pg_repack<\/a><\/noindex>. Ca principiu, este foarte asem\u0103n\u0103tor cu VACUUM FULL, deoarece la fel \u0219i acesta rescrie datele din fi\u0219ierele vechi \u00een cele noi \u0219i le schimb\u0103 \u00een tabel. Dar, \u00een acest proces, nu ia o blocare exclusiv\u0103 pe tabel la \u00eenceput, ci doar \u00een momentul \u00een care are deja datele gata pentru a schimba fi\u0219ierele. Cerin\u021bele pentru resursele de disc sunt similare cu cele ale VACUUM FULL. Ave\u021bi nevoie de spa\u021biu suplimentar pe disc, ceea ce poate fi critic, dac\u0103 ave\u021bi tabele de un terabyte. De asemenea, este destul de consumator de resurse CPU, deoarece lucreaz\u0103 activ cu I\/O. <\/li>\n<li>Al treilea utilitar este <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/dataegret\/pgcompacttable\">pgcompacttable<\/a><\/noindex>. Aceasta are o abordare mai atent\u0103 fa\u021b\u0103 de resurse, deoarece func\u021bioneaz\u0103 pe principii u\u0219or diferite. Esen\u021ba principal\u0103 a pgcompacttable este c\u0103, prin actualiz\u0103rile din tabel, mut\u0103 toate r\u00e2ndurile active la \u00eenceputul acestuia. Apoi, ruleaz\u0103 un vacuum pe acest tabel, deoarece \u0219tim c\u0103 avem la \u00eenceput r\u00e2nduri active \u0219i la sf\u00e2r\u0219it r\u00e2nduri moarte. \u0218i vacuum-ul taie deja acea parte de la sf\u00e2r\u0219it, adic\u0103 nu necesit\u0103 mult spa\u021biu de stocare suplimentar. \u00cen plus, acesta poate fi restr\u00e2ns \u0219i din punct de vedere al resurselor. <\/li>\n<\/ul>\n<p><\/p>\n<p>Cu instrumentele, totul este \u00een regul\u0103. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Erorile tipice \u00een aplica\u021bii care duc la bloat \u00een PostgreSQL. Andrei Salnikov\" src=\"\/wp-content\/uploads\/2020\/05\/4187915e54e54a0b85a342fe0280f78f.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Dac\u0103 v-au intrigat bloat-ul \u00een sensul de a cerceta mai departe, iat\u0103 c\u00e2teva linkuri utile:<\/p>\n<p><\/p>\n<ul>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/www.slideshare.net\/alexius2Mb\/where-is-the-space-postgres\">https:\/\/www.slideshare.net\/alexius2Mb\/where-is-the-space-postgres<\/a><\/noindex> \u2013 este o prezentare a colegului meu. Este o prezentare general\u0103 despre ce se \u00eent\u00e2mpl\u0103 cu spa\u021biul \u00een PostgreSQL pe parcursul func\u021bion\u0103rii \u0219i existen\u021bei sale. \u0218i acolo exist\u0103 o sec\u021biune tehnic\u0103 foarte mare \u0219i detaliat\u0103 pentru administratorii de baze de date despre bloat. <\/li>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/dataegret\/pg-utils\">https:\/\/github.com\/dataegret\/pg-utils<\/a><\/noindex> \u2013 acesta este un link c\u0103tre repository-ul nostru, unde p\u0103str\u0103m o mul\u021bime de scripturi utile pentru verificarea st\u0103rii bazei de date. Acolo pute\u021bi g\u0103si scripturi pentru identificarea bloat-ului. <\/li>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/reorg\/pg_repack\">Al treilea<\/a><\/noindex> \u0219i <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/dataegret\/pgcompacttable\">a patra<\/a><\/noindex> linkuri c\u0103tre instrumente care v\u0103 vor ajuta s\u0103 restr\u00e2nge\u021bi tabelele. <\/li>\n<li><noindex><a rel=\"nofollow\" href=\"http:\/\/blog.dataegret.com\/2Mb018\/03\/postgresql-bloatbusters.html\">http:\/\/blog.dataegret.com\/2Mb018\/03\/postgresql-bloatbusters.html<\/a><\/noindex> \u2013 acesta este un post al colegului meu. Acolo el analizeaz\u0103 \u00eentr-un mod destul de serios \u0219i tehnic bloat-ul, la un nivel apropiat de administratorii de baze de date. <\/li>\n<\/ul>\n<p><\/p>\n<p>Am \u00eencercat mai mult s\u0103 prezint o situa\u021bie alarmant\u0103 pentru dezvoltatori, deoarece ei sunt clien\u021bii no\u0219tri direc\u021bi \u0219i trebuie s\u0103 \u00een\u021beleag\u0103 la ce conduc anumite ac\u021biuni. Sper c\u0103 am reu\u0219it. V\u0103 mul\u021bumesc pentru aten\u021bie!<\/p>\n<p><\/p>\n<p>\u00centreb\u0103ri<\/p>\n<p><\/p>\n<p><em>V\u0103 mul\u021bumesc pentru prezentare! A\u021bi discutat despre cum pot fi identificate problemele. Cum pot fi prevenite? Adic\u0103, am avut o situa\u021bie c\u00e2nd interog\u0103rile au r\u0103mas suspendate nu doar din cauza c\u0103 s-au conectat la anumite servicii externe. Au fost doar ni\u0219te join-uri complicate. Au fost interog\u0103ri foarte mici, inofensive, care au r\u0103mas suspendate timp de o zi, iar apoi au \u00eenceput s\u0103 fac\u0103 anumite probleme. Adic\u0103, este foarte asem\u0103n\u0103tor cu ceea ce descrie\u021bi. Cum se poate monitoriza acest lucru? Trebuie s\u0103 stau tot timpul s\u0103 observ care interogare este suspendat\u0103? Cum se poate preveni asta?<\/em><\/p>\n<p><\/p>\n<p>\u00cen acest caz, aceasta este o responsabilitate pentru administratorii companiei dumneavoastr\u0103, nu neap\u0103rat pentru DBA.<\/p>\n<p><\/p>\n<p><em>Eu sunt administrator.<\/em><\/p>\n<p><\/p>\n<p>\u00cen PostgreSQL exist\u0103 o viziune numit\u0103 pg_stat_activity, \u00een care sunt afi\u0219ate interog\u0103rile suspendate. \u0218i pute\u021bi vedea c\u00e2t timp a r\u0103mas suspendat\u0103.<\/p>\n<p><\/p>\n<p><em>Trebuie s\u0103 m\u0103 conectez \u0219i s\u0103 verific la fiecare 5 minute?<\/em><\/p>\n<p><\/p>\n<p>Configura\u021bi cron-ul \u0219i verifica\u021bi. Dac\u0103 ave\u021bi o cerere lung\u0103, trimite\u021bi un e-mail \u0219i gata. Adic\u0103, nu trebuie s\u0103 urm\u0103ri\u021bi vizual, acest lucru poate fi automatizat. Ve\u021bi primi un e-mail, iar dumneavoastr\u0103 reac\u021biona\u021bi la el. Sau pute\u021bi s\u0103 automatiza\u021bi totul.<\/p>\n<p><\/p>\n<p><em>Exist\u0103 motive evidente pentru care se \u00eent\u00e2mpl\u0103 acest lucru?<\/em><\/p>\n<p><\/p>\n<p>Am enumerat c\u00e2teva. Exist\u0103 \u0219i alte exemple mai complexe. \u0218i acolo discu\u021bia poate dura mult.<\/p>\n<p><\/p>\n<p><em>Mul\u021bumesc pentru prezentare! A\u0219 dori s\u0103 clarific c\u00e2teva lucruri despre utilitarul pg_repack. Dac\u0103 nu face o blocare exclusiv\u0103, atunci\u2026<\/em><\/p>\n<p><\/p>\n<p>Face o blocare exclusiv\u0103. <\/p>\n<p><\/p>\n<p>\u2026 <em>atunci pot pierde poten\u021bial date. Aplica\u021bia mea nu ar trebui s\u0103 scrie nimic \u00een acest timp?<\/em><\/p>\n<p><\/p>\n<p>Nu, func\u021bioneaz\u0103 f\u0103r\u0103 probleme cu tabelul, adic\u0103 pg_repack mut\u0103 mai \u00eent\u00e2i toate \u00eenregistr\u0103rile active. Evident, se face o anumit\u0103 scriere \u00een tabel. El doar adaug\u0103 acea parte de final. <\/p>\n<p><\/p>\n<p><em>Adic\u0103, la final totu\u0219i face?<\/em><\/p>\n<p><\/p>\n<p>La final, ia o blocare exclusiv\u0103 pentru a schimba aceste fi\u0219iere \u00eentre ele. <\/p>\n<p><\/p>\n<p><em>Va fi mai rapid dec\u00e2t VACUUM FULL?<\/em><\/p>\n<p><\/p>\n<p>VACUUM FULL, de \u00eendat\u0103 ce \u00eencepe, ia imediat o blocare exclusiv\u0103. \u0218i p\u00e2n\u0103 c\u00e2nd nu finalizeaz\u0103 totul, nu o va elibera. \u00cen schimb, pg_repack ia o blocare exclusiv\u0103 doar \u00een momentul \u00eenlocuirii fi\u0219ierelor. \u00cen acel moment nu ve\u021bi putea scrie acolo, dar datele nu vor fi pierdute, totul va fi \u00een regul\u0103. <\/p>\n<p><\/p>\n<p><em>Bun\u0103 ziua! A\u021bi vorbit despre func\u021bionarea autovacuum-ului. Acolo a fost un grafic cu celule ro\u0219ii, galbene \u0219i verzi de \u00eenregistrare. Adic\u0103, galbene \u2013 le-a marcat ca fiind \u0219terse. \u0218i \u00een consecin\u021b\u0103, \u00een ele se pot scrie lucruri noi?<\/em><\/p>\n<p><\/p>\n<p>Da. Postgres nu \u0219terge \u00eenregistr\u0103rile. Are o astfel de specifica\u021bie. Dac\u0103 am actualizat o \u00eenregistrare, am marcat-o pe cea veche ca fiind \u0219tears\u0103. Se introduce ID-ul tranzac\u021biei care a modificat aceast\u0103 \u00eenregistrare, iar noi \u00eenregistr\u0103m o nou\u0103 \u00eenregistrare. \u0218i avem sesiuni care pot s\u0103 le citeasc\u0103 poten\u021bial. La un moment dat, ele devin foarte vechi. Iar scopul autovacuum-ului este s\u0103 parcurg\u0103 aceste \u00eenregistr\u0103ri \u0219i s\u0103 le marcheze ca fiind inutile. \u0218i acolo se pot rescrie date. <\/p>\n<p><\/p>\n<p><em>Am \u00een\u021beles. Dar \u00eentrebarea este pu\u021bin diferit\u0103. Nu am terminat. S\u0103 presupunem c\u0103 avem un tabel. \u00cen el sunt c\u00e2mpuri de dimensiune variabil\u0103. \u0218i dac\u0103 \u00eencerc s\u0103 introduc ceva nou, ar putea s\u0103 nu \u00eencap\u0103 \u00een vechea celul\u0103.<\/em> <\/p>\n<p><\/p>\n<p>Nu, \u00een orice caz, \u00eentreaga linie se actualizeaz\u0103. \u00cen Postgres exist\u0103 dou\u0103 modele de stocare a datelor. Acesta alege \u00een func\u021bie de tipul de date. Exist\u0103 date care sunt stocate direct \u00een tabel, iar altele sunt date tos. Acestea sunt volume mari de date: text, json. Ele sunt stocate \u00een tabele separate. \u0218i pentru aceste tabele se aplic\u0103 aceea\u0219i problem\u0103 cu bloat, adic\u0103 este totul la fel. Doar c\u0103 sunt separate. <\/p>\n<p><\/p>\n<p><em>Mul\u021bumesc pentru prezentare! C\u00e2t de acceptabil este s\u0103 folosim statement timeout pentru a limita durata cererilor?<\/em><\/p>\n<p><\/p>\n<p>Foarte acceptabil. Noi folosim asta peste tot. \u0218i deoarece nu avem servicii proprii, oferim suport remote, avem clien\u021bi destul de variati. \u0218i to\u021bi sunt destul de mul\u021bumi\u021bi de asta. Adic\u0103, avem sarcini \u00een cron care verific\u0103. Pur \u0219i simplu se discut\u0103 cu clientul despre durata sesiunilor, sub limita c\u0103reia nu intervenim. Aceasta poate fi de un minut sau de 10 minute. Depinde de \u00eenc\u0103rc\u0103tura bazei de date \u0219i de scopul acesteia. Dar to\u021bi folosim pg_stat_activity.<\/p>\n<p><\/p>\n<p><em>Mul\u021bumesc pentru prezentare! \u00cencerc s\u0103 aplic prezentarea dvs. la aplica\u021biile mele. \u0218i se pare c\u0103 \u00eencepem tranzi\u021biile peste tot, iar \u00een toate le \u00eencheiem clar. Dac\u0103 iau un exception, rollback-ul are loc oricum. \u0218i aici m-am g\u00e2ndit. Ar putea totu\u0219i s\u0103 \u00eenceap\u0103 o tranzac\u021bie \u00een mod implicit. Este un indiciu pentru fat\u0103, cred. Dac\u0103 pur \u0219i simplu fac o actualizare a unei \u00eenregistr\u0103ri, tranzac\u021bia va \u00eencepe \u00een PostgreSQL \u0219i se va \u00eencheia doar atunci c\u00e2nd va avea loc deconectarea?<\/em><\/p>\n<p><\/p>\n<p>Dac\u0103 vorbi\u021bi acum despre nivelul aplica\u021biei, depinde de driverul pe care \u00eel folosi\u021bi, de ORM-ul utilizat. Exist\u0103 foarte multe set\u0103ri. Dac\u0103 ave\u021bi activat auto commit on, atunci tranzac\u021bia va \u00eencepe \u0219i va fi imediat \u00eencheiat\u0103.<\/p>\n<p><\/p>\n<p><em>Deci, aceasta se \u00eencheie imediat dup\u0103 actualizare?<\/em><\/p>\n<p><\/p>\n<p>Asta depinde de set\u0103ri. Am men\u021bionat o setare. Este auto commit on. Este destul de comun\u0103. Dac\u0103 este activat\u0103, atunci tranzac\u021bia s-a deschis \u0219i s-a \u00eenchis. Dac\u0103 nu a\u021bi spus explicit \u201estart transaction\u201d \u0219i \u201eend transaction\u201d, ci a\u021bi lansat pur \u0219i simplu o interogare \u00een sesiune. <\/p>\n<p><\/p>\n<p><em>Bun\u0103 ziua! Mul\u021bumesc pentru prezentare! S\u0103 ne imagin\u0103m c\u0103 avem o baz\u0103 de date care devine voluminoas\u0103 \u0219i aici pe server se termin\u0103 spa\u021biul. Exist\u0103 instrumente pentru a corecta aceast\u0103 situa\u021bie?<\/em> <\/p>\n<p><\/p>\n<p>Spa\u021biul pe server, \u00een mod corect, trebuie monitorizat. <\/p>\n<p><\/p>\n<p><em>De exemplu, DBA a mers s\u0103 bea ceai, era \u00een vacan\u021b\u0103 etc.<\/em><\/p>\n<p><\/p>\n<p>C\u00e2nd se creeaz\u0103 un sistem de fi\u0219iere, exist\u0103 cel pu\u021bin un spa\u021biu rezervat creat, unde nu sunt scrise date. <\/p>\n<p><\/p>\n<p><em>Dar dac\u0103 este complet zero?<\/em><\/p>\n<p><\/p>\n<p>Se nume\u0219te spa\u021biu rezervat, adic\u0103 se poate elibera, iar \u00een func\u021bie de c\u00e2t de mare a fost creat, ob\u021bine\u021bi spa\u021biu liber. \u00cen mod implicit, nu \u0219tiu c\u00e2t este acolo. \u00cen alt caz, trebuie s\u0103 livra\u021bi discuri pentru a avea loc pentru a efectua opera\u021biunea de recuperare. Pute\u021bi \u0219terge o tabel\u0103 care, cu siguran\u021b\u0103, nu v\u0103 mai este necesar\u0103. <\/p>\n<p><\/p>\n<p><em>Nu exist\u0103 alte instrumente?<\/em><\/p>\n<p><\/p>\n<p>Este \u00eentotdeauna o munc\u0103 manual\u0103. \u0218i la fa\u021ba locului se stabile\u0219te ce ar trebui s\u0103 se fac\u0103, pentru c\u0103 exist\u0103 date critice \u0219i date non-critice. \u0218i pentru fiecare baz\u0103 de date \u0219i aplica\u021bie care lucreaz\u0103 cu aceasta, depinde de afacere. Este \u00eentotdeauna decizia luat\u0103 la fa\u021ba locului. <\/p>\n<p><\/p>\n<p><em>Mul\u021bumesc pentru prezentare! Am dou\u0103 \u00eentreb\u0103ri. \u00cen primul r\u00e2nd, a\u021bi demonstrat diapozitive \u00een care a\u021bi ar\u0103tat c\u0103, \u00een caz de tranzac\u021bii suspendate, at\u00e2t volumul spa\u021biului tabelar, c\u00e2t \u0219i dimensiunea indexului cresc. \u0218i mai departe \u00een prezentare au fost o mul\u021bime de utilitare care compacteaz\u0103 tabela. Dar ce se \u00eent\u00e2mpl\u0103 cu indexul?<\/em><\/p>\n<p><\/p>\n<p>Ele compactizeaz\u0103 \u0219i indexele. <\/p>\n<p><\/p>\n<p><em>Dar vacuumul nu atinge indexul?<\/em><\/p>\n<p><\/p>\n<p>Unele lucr\u0103ri cu indexul. De exemplu, pg_rapack, pgcompacttable. Vacuumul recreeaz\u0103 indexurile, le afecteaz\u0103. Scopul VACUUM FULL este s\u0103 rescrie totul, adic\u0103 lucreaz\u0103 cu toate. <\/p>\n<p><\/p>\n<p><em>\u0218i a doua \u00eentrebare. Nu am \u00een\u021beles de ce rapoartele de pe replici depind at\u00e2t de mult de replicare. Mi se p\u0103rea c\u0103 rapoartele sunt citiri, iar replicarea este scriere.<\/em> <\/p>\n<p><\/p>\n<p>\u00cen ce const\u0103 conflictul de replicare? Avem un Master, pe care se desf\u0103\u0219oar\u0103 procese. Avem un autovacuum. Ce face, de fapt, autovacuumul? Eliminaz\u0103 anumite r\u00e2nduri vechi. Dac\u0103 \u00een acel timp pe replic\u0103 exist\u0103 o cerere care cite\u0219te acele r\u00e2nduri vechi, iar pe Master a avut loc o situa\u021bie \u00een care autovacuumul a marcat acele r\u00e2nduri ca fiind posibile pentru rescriere, atunci le-am rescris. \u0218i ne-a venit un pachet de date c\u00e2nd trebuie s\u0103 rescriem acele r\u00e2nduri necesare cererii de pe replic\u0103, procesul de replicare va a\u0219tepta acel timeout pe care l-a\u021bi configurat. Apoi, PostgreSQL va decide ce este mai important pentru el. Iar replicarea este mai important\u0103 dec\u00e2t cererea \u0219i aceasta va fi respins\u0103 pentru a efectua modific\u0103rile pe replic\u0103. <\/p>\n<p><\/p>\n<p><em>Andrei, am o \u00eentrebare. Aceste grafice minunate pe care le-ai ar\u0103tat \u00een timpul prezent\u0103rii sunt rezultatul unor lucr\u0103ri ale unei utilitare de-a voastr\u0103? Cu ce a fost creat\u0103 grafica?<\/em><\/p>\n<p><\/p>\n<p>Este un serviciu <noindex><a rel=\"nofollow\" href=\"https:\/\/okmeter.io\/\">Okmeter<\/a><\/noindex>.<\/p>\n<p><\/p>\n<p><em>Este un produs comercial?<\/em><\/p>\n<p><\/p>\n<p>Da. Este un produs comercial.<\/p>\n<p>Sursa: <a content=\"nofollow\" rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/post\/501040\/\">habr.com<\/a> <\/p>","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"excerpt":{"rendered":"<p>\u041f\u0440\u0435\u0434\u043b\u0430\u0433\u0430\u044e \u043e\u0437\u043d\u0430\u043a\u043e\u043c\u0438\u0442\u044c\u0441\u044f \u0441 \u0440\u0430\u0441\u0448\u0438\u0444\u0440\u043e\u0432\u043a\u043e\u0439 \u0434\u043e\u043a\u043b\u0430\u0434\u0430 \u043d\u0430\u0447\u0430\u043b\u0430 2016 \u0433\u043e\u0434\u0430 \u0410\u043d\u0434\u0440\u0435\u044f \u0421\u0430\u043b\u044c\u043d\u0438\u043a\u043e\u0432\u0430 &quot;\u0422\u0438\u043f\u043e\u0432\u044b\u0435 \u043e\u0448\u0438\u0431\u043a\u0438 \u0432 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f\u0445, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0432\u0435\u0434\u0443\u0442 \u043a bloat \u0432 postgresql&quot; \u0412 \u0434\u0430\u043d\u043d\u043e\u043c \u0434\u043e\u043a\u043b\u0430\u0434\u0435 \u044f \u0440\u0430\u0437\u0431\u0435\u0440\u0443 \u043e\u0441\u043d\u043e\u0432\u043d\u044b\u0435 \u043e\u0448\u0438\u0431\u043a\u0438 \u0432 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f\u0445, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0432\u043e\u0437\u043d\u0438\u043a\u0430\u044e\u0442 \u043d\u0430 \u044d\u0442\u0430\u043f\u0435 \u043f\u0440\u043e\u0435\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0438 \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u044f \u043a\u043e\u0434\u0430 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f. \u0418 \u0432\u043e\u0437\u044c\u043c\u0443 \u0442\u043e\u043b\u044c\u043a\u043e \u0442\u0435 \u043e\u0448\u0438\u0431\u043a\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0432\u0435\u0434\u0443\u0442 \u043a bloat \u0432 Postgresql. \u041a\u0430\u043a \u043f\u0440\u0430\u0432\u0438\u043b\u043e, \u044d\u0442\u043e \u043d\u0430\u0447\u0430\u043b\u043e \u043a\u043e\u043d\u0446\u0430 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u0438 [&hellip;]<\/p>\n","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"author":1,"featured_media":81090,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[688],"tags":[],"class_list":["post-81089","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-administrirovanie"],"aioseo_notices":[],"aioseo_head":"\n\t\t<!-- All in One SEO 5.0.2.1 - aioseo.com -->\n\t<meta name=\"description\" content=\"\u041f\u0440\u0435\u0434\u043b\u0430\u0433\u0430\u044e \u043e\u0437\u043d\u0430\u043a\u043e\u043c\u0438\u0442\u044c\u0441\u044f \u0441 \u0440\u0430\u0441\u0448\u0438\u0444\u0440\u043e\u0432\u043a\u043e\u0439 \u0434\u043e\u043a\u043b\u0430\u0434\u0430 \u043d\u0430\u0447\u0430\u043b\u0430 2016 \u0433\u043e\u0434\u0430 \u0410\u043d\u0434\u0440\u0435\u044f \u0421\u0430\u043b\u044c\u043d\u0438\u043a\u043e\u0432\u0430 &quot;\u0422\u0438\u043f\u043e\u0432\u044b\u0435 \u043e\u0448\u0438\u0431\u043a\u0438 \u0432 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f\u0445, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0432\u0435\u0434\u0443\u0442 \u043a bloat \u0432 postgresql&quot; \u0412 \u0434\u0430\u043d\u043d\u043e\u043c \u0434\u043e\u043a\u043b\u0430\u0434\u0435 \u044f \u0440\u0430\u0437\u0431\u0435\u0440\u0443 \u043e\u0441\u043d\u043e\u0432\u043d\u044b\u0435.\" \/>\n\t<meta name=\"robots\" content=\"max-image-preview:large\" \/>\n\t<meta name=\"author\" content=\"Yuri Gagarin\"\/>\n\t<link rel=\"canonical\" href=\"https:\/\/prohoster.info\/ro\/blog\/administrirovanie\/tipovye-oshibki-v-prilozheniyah-kotorye-vedut-k-bloat-v-postgresql-andrej-salnikov\" \/>\n\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.2.1\" \/>\n\t\t<meta property=\"og:locale\" content=\"ro_RO\" \/>\n\t\t<meta property=\"og:site_name\" content=\"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b\" \/>\n\t\t<meta property=\"og:type\" content=\"article\" \/>\n\t\t<meta property=\"og:title\" content=\"\ud83e\udd47\u0422\u0438\u043f\u043e\u0432\u044b\u0435 \u043e\u0448\u0438\u0431\u043a\u0438 \u0432 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f\u0445, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0432\u0435\u0434\u0443\u0442 \u043a bloat \u0432 postgresql. \u0410\u043d\u0434\u0440\u0435\u0439 \u0421\u0430\u043b\u044c\u043d\u0438\u043a\u043e\u0432 | ProHoster\" \/>\n\t\t<meta property=\"og:description\" content=\"\u041f\u0440\u0435\u0434\u043b\u0430\u0433\u0430\u044e \u043e\u0437\u043d\u0430\u043a\u043e\u043c\u0438\u0442\u044c\u0441\u044f \u0441 \u0440\u0430\u0441\u0448\u0438\u0444\u0440\u043e\u0432\u043a\u043e\u0439 \u0434\u043e\u043a\u043b\u0430\u0434\u0430 \u043d\u0430\u0447\u0430\u043b\u0430 2016 \u0433\u043e\u0434\u0430 \u0410\u043d\u0434\u0440\u0435\u044f \u0421\u0430\u043b\u044c\u043d\u0438\u043a\u043e\u0432\u0430 &quot;\u0422\u0438\u043f\u043e\u0432\u044b\u0435 \u043e\u0448\u0438\u0431\u043a\u0438 \u0432 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f\u0445, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0432\u0435\u0434\u0443\u0442 \u043a bloat \u0432 postgresql&quot; \u0412 \u0434\u0430\u043d\u043d\u043e\u043c \u0434\u043e\u043a\u043b\u0430\u0434\u0435 \u044f \u0440\u0430\u0437\u0431\u0435\u0440\u0443 \u043e\u0441\u043d\u043e\u0432\u043d\u044b\u0435.\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/prohoster.info\/ro\/blog\/administrirovanie\/tipovye-oshibki-v-prilozheniyah-kotorye-vedut-k-bloat-v-postgresql-andrej-salnikov\" \/>\n\t\t<meta property=\"og:image\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:secure_url\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:width\" content=\"350\" \/>\n\t\t<meta property=\"og:image:height\" content=\"350\" \/>\n\t\t<meta property=\"article:published_time\" content=\"2020-05-10T23:42:24+00:00\" \/>\n\t\t<meta property=\"article:modified_time\" content=\"2020-05-10T23:42:24+00:00\" \/>\n\t\t<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<meta property=\"article:author\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<!-- All in One SEO -->\n\n","aioseo_head_json":{"title":"\ud83e\udd47Erori tipice \u00een aplica\u021bii care duc la bloat \u00een PostgreSQL. Andrei Salnikov | ProHoster","description":"\u00ce\u021bi propun s\u0103 consul\u021bi decriptarea raportului din \u00eenceputul anului 2016 al lui Andrei Salnikov \"Erori tipice \u00een aplica\u021bii care duc la bloat \u00een PostgreSQL\". \u00cen acest raport voi analiza principalele.","canonical_url":"https:\/\/prohoster.info\/ro\/blog\/administrirovanie\/tipovye-oshibki-v-prilozheniyah-kotorye-vedut-k-bloat-v-postgresql-andrej-salnikov","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"ro_RO","og:site_name":"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b","og:type":"article","og:title":"\ud83e\udd47\u0422\u0438\u043f\u043e\u0432\u044b\u0435 \u043e\u0448\u0438\u0431\u043a\u0438 \u0432 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f\u0445, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0432\u0435\u0434\u0443\u0442 \u043a bloat \u0432 postgresql. \u0410\u043d\u0434\u0440\u0435\u0439 \u0421\u0430\u043b\u044c\u043d\u0438\u043a\u043e\u0432 | ProHoster","og:description":"\u041f\u0440\u0435\u0434\u043b\u0430\u0433\u0430\u044e \u043e\u0437\u043d\u0430\u043a\u043e\u043c\u0438\u0442\u044c\u0441\u044f \u0441 \u0440\u0430\u0441\u0448\u0438\u0444\u0440\u043e\u0432\u043a\u043e\u0439 \u0434\u043e\u043a\u043b\u0430\u0434\u0430 \u043d\u0430\u0447\u0430\u043b\u0430 2016 \u0433\u043e\u0434\u0430 \u0410\u043d\u0434\u0440\u0435\u044f \u0421\u0430\u043b\u044c\u043d\u0438\u043a\u043e\u0432\u0430 &quot;\u0422\u0438\u043f\u043e\u0432\u044b\u0435 \u043e\u0448\u0438\u0431\u043a\u0438 \u0432 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f\u0445, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0432\u0435\u0434\u0443\u0442 \u043a bloat \u0432 postgresql&quot; \u0412 \u0434\u0430\u043d\u043d\u043e\u043c \u0434\u043e\u043a\u043b\u0430\u0434\u0435 \u044f \u0440\u0430\u0437\u0431\u0435\u0440\u0443 \u043e\u0441\u043d\u043e\u0432\u043d\u044b\u0435.","og:url":"https:\/\/prohoster.info\/ro\/blog\/administrirovanie\/tipovye-oshibki-v-prilozheniyah-kotorye-vedut-k-bloat-v-postgresql-andrej-salnikov","og:image":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:secure_url":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:width":350,"og:image:height":350,"article:published_time":"2020-05-10T23:42:24+00:00","article:modified_time":"2020-05-10T23:42:24+00:00","article:publisher":"https:\/\/www.facebook.com\/prohoster","article:author":"https:\/\/www.facebook.com\/prohoster"},"aioseo_meta_data":{"post_id":"81089","title":null,"description":null,"keywords":null,"keyphrases":null,"primary_term":null,"canonical_url":null,"og_title":null,"og_description":null,"og_object_type":"default","og_image_type":"default","og_image_url":null,"og_image_width":null,"og_image_height":null,"og_image_custom_url":null,"og_image_custom_fields":null,"og_video":null,"og_custom_url":null,"og_article_section":null,"og_article_tags":null,"twitter_use_og":false,"twitter_card":"default","twitter_image_type":"default","twitter_image_url":null,"twitter_image_custom_url":null,"twitter_image_custom_fields":null,"twitter_title":null,"twitter_description":null,"schema":{"blockGraphs":[],"customGraphs":[],"default":{"data":{"Article":[],"Course":[],"Dataset":[],"FAQPage":[],"Movie":[],"Person":[],"Product":[],"ProductReview":[],"Car":[],"Recipe":[],"Service":[],"SoftwareApplication":[],"WebPage":[]},"graphName":"","isEnabled":true},"graphs":[]},"schema_type":null,"schema_type_options":null,"pillar_content":false,"robots_default":true,"robots_noindex":false,"robots_noarchive":false,"robots_nosnippet":false,"robots_nofollow":false,"robots_noimageindex":false,"robots_noodp":false,"robots_notranslate":false,"robots_max_snippet":null,"robots_max_videopreview":null,"robots_max_imagepreview":"large","priority":null,"frequency":null,"local_seo":null,"seo_analyzer_scan_date":null,"breadcrumb_settings":null,"limit_modified_date":false,"reviewed_by":null,"ai":null,"created":"2021-02-28 16:05:22","updated":"2022-09-27 16:01:50","focus_keyword":null,"additional_keywords":null,"truseo_locale":null},"gt_translate_keys":[{"key":"link","format":"url"}],"_links":{"self":[{"href":"https:\/\/prohoster.info\/ro\/wp-json\/wp\/v2\/posts\/81089","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/ro\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/ro\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/ro\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/ro\/wp-json\/wp\/v2\/comments?post=81089"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/ro\/wp-json\/wp\/v2\/posts\/81089\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/ro\/wp-json\/wp\/v2\/media\/81090"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/ro\/wp-json\/wp\/v2\/media?parent=81089"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/ro\/wp-json\/wp\/v2\/categories?post=81089"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/ro\/wp-json\/wp\/v2\/tags?post=81089"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}