{"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\/de\/blog\/administrirovanie\/tipovye-oshibki-v-prilozheniyah-kotorye-vedut-k-bloat-v-postgresql-andrej-salnikov","title":{"rendered":"Typische Fehler in Anwendungen, die zu Bloat in PostgreSQL f\u00fchren. Andrey Salnikov","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p><strong>Ich lade Sie ein, sich mit der Auswertung des Berichts von Andrej Salnikow aus Anfang 2016 \"Typische Fehler in Anwendungen, die zu Bloat in PostgreSQL f\u00fchren\" vertraut zu machen.<\/strong><\/p>\n<p><\/p>\n<p>In diesem Bericht werde ich die h\u00e4ufigsten Fehler in Anwendungen behandeln, die in der Phase des Designs und des Schreibens des Anwendungscodes auftreten. Ich werde nur die Fehler betrachten, die zu Bloat in PostgreSQL f\u00fchren. In der Regel ist dies der Anfang vom Ende der Leistungsf\u00e4higkeit Ihres Systems insgesamt, obwohl anfangs keine Anzeichen daf\u00fcr zu erkennen waren.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Typische Fehler in Anwendungen, die zu Bloat in PostgreSQL f\u00fchren. Andrey 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>Ich begr\u00fc\u00dfe alle herzlich! Dieser Bericht ist nicht so technisch wie der vorherige von meinem Kollegen. Dieser Bericht richtet sich haupts\u00e4chlich an Entwickler von Backend-Systemen, da wir eine ziemlich gro\u00dfe Anzahl von Kunden haben. Und alle machen die gleichen Fehler. Ich werde dar\u00fcber sprechen. Ich erkl\u00e4re, welche katastrophalen und negativen Folgen diese Fehler haben k\u00f6nnen. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Typische Fehler in Anwendungen, die zu Bloat in PostgreSQL f\u00fchren. Andrey Salnikov\" src=\"\/wp-content\/uploads\/2020\/05\/c6c84dbafc595ae3068cd8bf804ccee7.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Warum werden Fehler gemacht? Sie entstehen aus zwei Gr\u00fcnden: aus einer gewissen Unbek\u00fcmmertheit \u2013 vielleicht klappt es ja so \u2013 und aus Unkenntnis \u00fcber bestimmte Mechanismen, die auf der Ebene zwischen der Datenbank und der Anwendung sowie in der Datenbank selbst stattfinden. <\/p>\n<p><\/p>\n<p>Ich werde Ihnen drei Beispiele mit schrecklichen Bildern zeigen, wie alles schlecht geworden ist. Ich werde kurz den Mechanismus erkl\u00e4ren, der dort abl\u00e4uft. Und wie man damit umgeht, wenn sie auftreten, und welche pr\u00e4ventiven Methoden man anwenden kann, um Fehler zu verhindern. Ich werde \u00fcber Hilfsmittel sprechen und n\u00fctzliche Links bereitstellen. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Typische Fehler in Anwendungen, die zu Bloat in PostgreSQL f\u00fchren. Andrey Salnikov\" src=\"\/wp-content\/uploads\/2020\/05\/b0230d992f5b44f0e542df2e4b4d526f.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Ich habe eine Testdatenbank verwendet, in der ich zwei Tabellen hatte. Eine Tabelle mit den Konten der Kunden, die andere mit den Transaktionen f\u00fcr diese Konten. Und in regelm\u00e4\u00dfigen Abst\u00e4nden aktualisieren wir die Salden dieser Konten.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Typische Fehler in Anwendungen, die zu Bloat in PostgreSQL f\u00fchren. Andrey Salnikov\" src=\"\/wp-content\/uploads\/2020\/05\/1d2a21278b095b07546e1bb870819dbf.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Die Ausgangsdaten der Tabelle: sie ist recht klein, 2 MB. Die Antwortzeiten f\u00fcr die Datenbank und speziell f\u00fcr die Tabelle sind ebenfalls sehr gut. Und die Last ist ebenfalls gut \u2013 2.000 Transaktionen pro Sekunde f\u00fcr die Tabelle.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Typische Fehler in Anwendungen, die zu Bloat in PostgreSQL f\u00fchren. Andrey Salnikov\" src=\"\/wp-content\/uploads\/2020\/05\/dea5a4b1ac7952f8cfed0e2e1cfc10dd.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Und durch diesen Bericht werde ich Ihnen Grafiken zeigen, um anschaulich zu demonstrieren, was passiert. Es wird immer zwei Folien mit Grafiken geben. Die erste Folie zeigt, was insgesamt auf dem Server passiert. <\/p>\n<p><\/p>\n<p>Und in dieser Situation sehen wir, dass unsere Tabelle tats\u00e4chlich klein ist. Der Index ist klein und betr\u00e4gt 2 MB. Das ist das erste Diagramm von links. <\/p>\n<p><\/p>\n<p>Die durchschnittliche Antwortzeit des Servers ist ebenfalls stabil und gering. Das ist das obere rechte Diagramm. <\/p>\n<p><\/p>\n<p>Das linke untere Diagramm zeigt die l\u00e4ngeren Transaktionen. Wir sehen, dass die Transaktionen schnell ausgef\u00fchrt werden. Und der Auto-Vakuum funktioniert hier noch nicht, da es sich um einen Start-Test handelte. In Zukunft wird er funktionieren und uns n\u00fctzlich sein.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Typische Fehler in Anwendungen, die zu Bloat in PostgreSQL f\u00fchren. Andrey Salnikov\" src=\"\/wp-content\/uploads\/2020\/05\/9e9b46acd9a878ff70ca4a7850adff09.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Die zweite Folie ist immer der Testtabelle gewidmet. In dieser Situation aktualisieren wir kontinuierlich die Best\u00e4nde auf den Konten des Kunden. Wir sehen, dass die durchschnittliche Antwortzeit f\u00fcr die Aktualisierungsoperationen ziemlich gut ist, weniger als eine Millisekunde. Wir sehen auch, dass die Ressourcen des Prozessors (das ist das rechte obere Diagramm) gleichm\u00e4\u00dfig und recht gering verbraucht werden. <\/p>\n<p><\/p>\n<p>Das rechte untere Diagramm zeigt, wie viel Arbeitsspeicher und Festplattenspeicher wir durchsuchen, um unsere ben\u00f6tigte Zeile zu finden, bevor wir sie aktualisieren. Und die Anzahl der Operationen auf der Tabelle \u2013 2.000 pro Sekunde, wie ich zu Beginn gesagt habe. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Typische Fehler in Anwendungen, die zu Bloat in PostgreSQL f\u00fchren. Andrey Salnikov\" src=\"\/wp-content\/uploads\/2020\/05\/84760d52716209b8dcfffb462c67a8e1.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Und jetzt passiert eine Trag\u00f6die. Aus irgendeinem Grund tritt eine lange vergessene Transaktion auf. Die Ursachen sind normalerweise banal: <\/p>\n<p><\/p>\n<ul>\n<li>Eine der h\u00e4ufigsten Ursachen ist, dass wir im Anwendungscode begonnen haben, auf einen externen Dienst zuzugreifen. Und dieser Dienst antwortet uns nicht. Das hei\u00dft, wir haben eine Transaktion er\u00f6ffnet, \u00c4nderungen in der Datenbank vorgenommen und sind aus der Anwendung gegangen, um die E-Mails zu lesen oder zu einem anderen Dienst in unserer Infrastruktur zu wechseln, und dieser antwortet aus irgendeinem Grund nicht. Und wir haben eine Sitzung, die im Status h\u00e4ngt \u2013 unklar, wann sie gel\u00f6st wird.<\/li>\n<li>Die zweite Situation ist, wenn im Code aus irgendeinem Grund eine Ausnahme aufgetreten ist. Und wir haben in der Ausnahme das Schlie\u00dfen der Transaktion nicht behandelt. Und wir haben eine h\u00e4ngende Sitzung mit einer offenen Transaktion. <\/li>\n<li>Und der letzte Fall \u2013 das ist auch ein h\u00e4ufiges Ph\u00e4nomen. Das ist minderwertiger Code. Einige Frameworks er\u00f6ffnen eine Transaktion. Sie h\u00e4ngt, und Sie k\u00f6nnten nicht wissen, dass sie in Ihrer Anwendung h\u00e4ngt. <\/li>\n<\/ul>\n<p><\/p>\n<p>Was f\u00fchren solche Dinge zur Folge? <\/p>\n<p><\/p>\n<p>Dazu, dass unsere Tabellen und Indizes stark anwachsen. Das ist genau der Effekt der Aufbl\u00e4hung. F\u00fcr die Datenbank wird sich das in einer drastischen Erh\u00f6hung der Antwortzeit der Datenbank \u00e4u\u00dfern, und die Belastung des Datenbankservers wird steigen. Als Ergebnis wird die Anwendung leiden. Denn wenn Sie im Code 10 Millisekunden f\u00fcr eine Anfrage an die Datenbank und 10 Millisekunden f\u00fcr Ihre Logik aufgewendet haben, dann arbeitete Ihre Funktion in 20 Millisekunden. Jetzt wird Ihre Situation jedoch ganz traurig sein. <\/p>\n<p><\/p>\n<p>Und lassen Sie uns sehen, was passiert. Das linke untere Diagramm zeigt, dass wir eine lange, ausgedehnte Transaktion haben. Und wenn wir uns das obere linke Diagramm ansehen, sehen wir, dass sich die Gr\u00f6\u00dfe der Tabelle von zwei Megabyte pl\u00f6tzlich auf 300 Megabyte erh\u00f6ht hat. Dabei hat sich die Datenmenge in der Tabelle nicht ver\u00e4ndert, d. h. es gibt eine betr\u00e4chtliche Menge an M\u00fcll.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Typische Fehler in Anwendungen, die zu Bloat in PostgreSQL f\u00fchren. Andrey Salnikov\" src=\"\/wp-content\/uploads\/2020\/05\/b1947f6487e440a770a1251a955e62d2.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Die allgemeine Situation hinsichtlich der durchschnittlichen Serverantwortzeit hat sich ebenfalls um mehrere Gr\u00f6\u00dfenordnungen ver\u00e4ndert. Das bedeutet, dass alle Anfragen an den Server erheblich langsamer geworden sind. Und dabei haben interne Prozesse von Postgres in Form des Autovacuum-Tools begonnen, etwas zu versuchen und Ressourcen zu verbrauchen.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Typische Fehler in Anwendungen, die zu Bloat in PostgreSQL f\u00fchren. Andrey Salnikov\" src=\"\/wp-content\/uploads\/2020\/05\/8e91f035d1dd04e72e842d714cc611a5.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Was passiert also mit unserer Tabelle? Dasselbe. Die durchschnittliche Antwortzeit f\u00fcr die Tabelle ist um mehrere Gr\u00f6\u00dfenordnungen angestiegen. Konkrete Auswirkungen auf die verbrauchten Ressourcen zeigen, dass die Belastung der CPU stark gestiegen ist. Dies ist das obere rechte Diagramm. Es hat zugenommen, weil die CPU eine Menge nutzloser Zeilen durchforsten muss, um eine ben\u00f6tigte zu finden. Dies ist das untere rechte Diagramm. Und als Ergebnis hat die Anzahl der Aufrufe pro Sekunde stark abgenommen, da die Datenbank nicht in der Lage ist, die gleiche Anzahl von Anfragen zu bearbeiten. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Typische Fehler in Anwendungen, die zu Bloat in PostgreSQL f\u00fchren. Andrey Salnikov\" src=\"\/wp-content\/uploads\/2020\/05\/424685ce852bc5f3ef77151f8d3d7289.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Wir m\u00fcssen wieder ins Leben zur\u00fcckkehren. Wir gehen ins Internet und erfahren, dass lange Transaktionen zu Problemen f\u00fchren. Wir finden und beenden diese Transaktion. Und alles wird wieder normal. Alles funktioniert wie gew\u00fcnscht. <\/p>\n<p><\/p>\n<p>Wir beruhigen uns, doch nach einiger Zeit bemerken wir, dass die Anwendung nicht mehr so funktioniert wie vor dem Ausfall. Die Anfragen werden dennoch langsamer bearbeitet, und zwar erheblich langsamer. Im Beispiel meiner Situation um eineinhalb bis zweimal langsamer. Die Serverlast ist ebenfalls h\u00f6her als vor dem Ausfall. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Typische Fehler in Anwendungen, die zu Bloat in PostgreSQL f\u00fchren. Andrey Salnikov\" src=\"\/wp-content\/uploads\/2020\/05\/ee3037719a31f8d18fc42745716c4da5.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Und die Frage lautet: \u201eWas passiert in diesem Moment mit der Datenbank?\u201c. Mit der Datenbank passiert Folgendes. Im Diagramm der Transaktionen sehen Sie, dass sie gestoppt ist und es tats\u00e4chlich keine langen Transaktionen gibt. Aber die Gr\u00f6\u00dfen der Tabelle sind w\u00e4hrend des Ausfalls katastrophal gestiegen. Und seitdem sind sie nicht mehr gesunken. Die durchschnittliche Zeit der Datenbank hat sich stabilisiert. Die Antworten scheinen in einem f\u00fcr uns akzeptablen Tempo zu kommen. Der Autovacuum-Prozess ist aktiver geworden und hat begonnen, etwas mit der Tabelle zu machen, weil er eine gr\u00f6\u00dfere Menge an Daten verarbeiten muss. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Typische Fehler in Anwendungen, die zu Bloat in PostgreSQL f\u00fchren. Andrey Salnikov\" src=\"\/wp-content\/uploads\/2020\/05\/f6205242c4024dc3ed4cade5844dbf76.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Bez\u00fcglich der getesteten Tabelle mit den Abrechnungen, wo wir die Reste \u00e4ndern: Die Antwortzeit auf die Anfrage scheint sich normalisiert zu haben. Aber in der Tat liegt sie anderthalb Mal h\u00f6her.<\/p>\n<p><\/p>\n<p>Und bez\u00fcglich der CPU-Auslastung sehen wir, dass die CPU-Belastung bis zur Panne nicht wieder auf die erforderlichen Werte zur\u00fcckgekehrt ist. Die Ursachen verstecken sich gerade im rechten unteren Diagramm. Man sieht, dass hier eine \u00dcberpr\u00fcfung einer bestimmten Menge von Speicher stattfindet. Das hei\u00dft, um die ben\u00f6tigte Zeile zu finden, verbrauchen wir die Ressourcen des Servers, w\u00e4hrend wir durch nutzlose Daten durchforsten. Die Anzahl der Transaktionen pro Sekunde hat sich stabilisiert. <\/p>\n<p><\/p>\n<p>Insgesamt ist es gut, aber die Situation ist schlimmer als zuvor. Eine offensichtliche Degeneration der Datenbank als Folge unserer Anwendung, die mit dieser Datenbank arbeitet. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Typische Fehler in Anwendungen, die zu Bloat in PostgreSQL f\u00fchren. Andrey Salnikov\" src=\"\/wp-content\/uploads\/2020\/05\/0dfc9cd453fd84bc639ffd99cf189fd2.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Um zu verstehen, was dort passiert, falls Sie nicht bei dem vorherigen Bericht waren, gibt es jetzt ein wenig Theorie. Die Theorie \u00fcber den internen Prozess. Warum ben\u00f6tigen wir den Autovacuum und was macht er?<\/p>\n<p><\/p>\n<p>Kurz gesagt, um es zu verstehen. Zu einem bestimmten Zeitpunkt haben wir eine Tabelle. In der Tabelle befinden sich Zeilen. Diese Zeilen k\u00f6nnen aktiv, lebendig und jetzt f\u00fcr uns wichtig sein. Im Bild sind sie gr\u00fcn markiert. Es gibt auch tote Zeilen, die bereits verarbeitet wurden, aktualisiert wurden und f\u00fcr die neue Eintr\u00e4ge erschienen sind. Und sie sind markiert, dass sie der Datenbank nicht mehr von Interesse sind. Aber sie liegen aufgrund der Besonderheit von Postgres in der Tabelle.<\/p>\n<p><\/p>\n<p>Warum ben\u00f6tigen wir den Autovacuum? Der Autovacuum fragt irgendwann die Datenbank und sagt: \u201eGib mir bitte die ID der \u00e4ltesten Transaktion, die derzeit in der Datenbank ge\u00f6ffnet ist\u201c. Die Datenbank gibt diese ID zur\u00fcck. Und der Autovacuum greift darauf zur\u00fcck und durchforstet die Zeilen in der Tabelle. Wenn er sieht, dass einige Zeilen von wesentlich \u00e4lteren Transaktionen ver\u00e4ndert wurden, hat er das Recht, sie als Zeilen zu kennzeichnen, die wir in Zukunft wiederverwenden k\u00f6nnen, indem wir dort neue Daten schreiben. Dies ist ein Hintergrundprozess.<\/p>\n<p><\/p>\n<p>In der Zwischenzeit arbeiten wir weiterhin mit der Datenbank, f\u00fchren \u00c4nderungen in der Tabelle durch. Und in diese Zeilen, die wir wiederverwenden k\u00f6nnen, schreiben wir neue Daten. So entsteht ein Kreislauf, das hei\u00dft, es gibt st\u00e4ndig alte tote Zeilen, und an ihrer Stelle schreiben wir neue Zeilen, die wir ben\u00f6tigen. Und das ist ein normaler Zustand f\u00fcr die Arbeit von PostgreSQL.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Typische Fehler in Anwendungen, die zu Bloat in PostgreSQL f\u00fchren. Andrey Salnikov\" src=\"\/wp-content\/uploads\/2020\/05\/98dd4451a7ca5f418775f72822c2840c.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Was ist w\u00e4hrend des Vorfalls passiert? Wie hat dieser Prozess stattgefunden?<\/p>\n<p><\/p>\n<p>Wir hatten eine Tabelle in einem bestimmten Zustand, einige lebende, einige tote Zeilen. Der Autovacuum kam. Er fragte die Datenbank nach der \u00e4ltesten Transaktion, die wir haben, welcher ID sie hat. Er erhielt diese ID, die viele Stunden zur\u00fcckliegen k\u00f6nnte, vielleicht nur zehn Minuten. Das h\u00e4ngt davon ab, wie stark die Last in Ihrer Datenbank ist. Und er ging auf die Suche nach Zeilen, die er als wiederverwendbar markieren kann. Und er fand keine solchen Zeilen in unserer Tabelle. <\/p>\n<p><\/p>\n<p>Aber wir arbeiten in der Zwischenzeit weiter an der Tabelle. Wir tun etwas darin, aktualisieren, \u00e4ndern Daten. Und was kann die Datenbank in dieser Zeit tun? Sie kann nichts anderes tun, als neue Zeilen am Ende der bestehenden Tabelle hinzuzuf\u00fcgen. Dadurch beginnt die Gr\u00f6\u00dfe der Tabelle zu wachsen. <\/p>\n<p><\/p>\n<p>In Wirklichkeit ben\u00f6tigen wir f\u00fcr die Arbeit gr\u00fcne Zeilen. Aber w\u00e4hrend eines solchen Problems haben wir, dass der Anteil gr\u00fcner Zeilen im gesamten Volumen der Tabelle extrem niedrig ist. <\/p>\n<p><\/p>\n<p>Wenn wir jedoch eine Abfrage durchf\u00fchren, muss die Datenbank durch alle Zeilen gehen: sowohl rote als auch gr\u00fcne, um die ben\u00f6tigte Zeile zu finden. Und der Effekt der Aufbl\u00e4hung der Tabelle mit nutzlosen Daten hei\u00dft 'Bloat', das auch unseren Speicherplatz frisst. Erinnern Sie sich, es waren 2 MB, es wurden 300 MB? Und jetzt tauschen Sie Megabyte gegen Gigabyte aus und Sie werden recht schnell all Ihre Speicherkapazit\u00e4ten verlieren.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Typische Fehler in Anwendungen, die zu Bloat in PostgreSQL f\u00fchren. Andrey Salnikov\" src=\"\/wp-content\/uploads\/2020\/05\/fe7cb6b5c99610744ebcfe5ad7235d1e.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Welche Folgen kann das f\u00fcr uns haben? <\/p>\n<p><\/p>\n<ul>\n<li>In meinem Beispiel ist die Tabelle und der Index um das 150-fache gewachsen. Einige unserer Kunden hatten noch fatalere F\u00e4lle, als der Speicherplatz auf der Festplatte zu Ende ging. <\/li>\n<li>Die Gr\u00f6\u00dfe der Tabellen wird sich nie von selbst verringern. Der Autovacuum kann in einigen F\u00e4llen das Ende der Tabelle abschneiden, wenn dort nur tote Zeilen sind. Aber da eine st\u00e4ndige Rotation stattfindet, k\u00f6nnte eine gr\u00fcne Zeile am Ende h\u00e4ngen bleiben und nicht aktualisiert werden, w\u00e4hrend alle anderen irgendwo am Anfang der Tabelle geschrieben werden. Aber das ist ein so unwahrscheinliches Ereignis, dass man nicht darauf hoffen sollte, dass sich die Tabelle von selbst verkleinert. <\/li>\n<li>Die Datenbank muss durch einen Haufen nutzloser Zeilen gehen. Und wir verschwenden Speicherressourcen, CPU-Ressourcen und Elektrizit\u00e4t. <\/li>\n<li>Und das hat direkte Auswirkungen auf unsere Anwendung, denn wenn wir am Anfang 10 Millisekunden f\u00fcr die Anfrage und 10 Millisekunden f\u00fcr unseren Code ben\u00f6tigten, verbrauchten wir w\u00e4hrend des Ausfalls eine Sekunde f\u00fcr die Anfrage und 10 Millisekunden f\u00fcr den Code, d. h. die Leistung der Anwendung hat sich um den Faktor 10 verschlechtert. Und als der Ausfall behoben wurde, ben\u00f6tigten wir 20 Millisekunden f\u00fcr die Anfrage und 10 Millisekunden f\u00fcr den Code. Das bedeutet, dass wir immer noch um das 1,5-fache in der Leistung gefallen sind. Und das alles wegen einer Transaktion, die festhing, m\u00f6glicherweise aufgrund unseres Verschuldens. <\/li>\n<li>Und die Frage ist: \u201eWie k\u00f6nnen wir alles zur\u00fcckbringen?\u201c, damit alles gut wird und die Anfragen so schnell laufen wie vor dem Ausfall. <\/li>\n<\/ul>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Typische Fehler in Anwendungen, die zu Bloat in PostgreSQL f\u00fchren. Andrey Salnikov\" src=\"\/wp-content\/uploads\/2020\/05\/1bf46e8cd9b28ca2862f978f2ca85819.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Daf\u00fcr gibt es einen bestimmten Arbeitszyklus, der durchgef\u00fchrt werden muss. <\/p>\n<p><\/p>\n<p>Zun\u00e4chst m\u00fcssen wir die problematischen Tabellen finden, die aufgebl\u00e4ht sind. Wir verstehen, dass einige Tabellen aktiver beschreiben, andere weniger aktiv. Daf\u00fcr wird die Erweiterung <noindex><a rel=\"nofollow\" href=\"https:\/\/www.postgresql.org\/docs\/current\/pgstattuple.html\">pgstattuple<\/a><\/noindex>verwendet. Mit dieser Erweiterung k\u00f6nnen Sie Abfragen schreiben, die Ihnen helfen, die Tabellen zu finden, die sich stark aufgebl\u00e4ht haben. <\/p>\n<p><\/p>\n<p>Nachdem Sie diese Tabellen gefunden haben, m\u00fcssen sie komprimiert werden. Daf\u00fcr gibt es bereits Werkzeuge. In unserem Unternehmen verwenden wir drei Werkzeuge. Das erste ist das integrierte VACUUM FULL. Es ist brutal, hart und schonungslos, aber manchmal ist es sehr n\u00fctzlich. <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/reorg\/pg_repack\">Pg_repack<\/a><\/noindex> und <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/dataegret\/pgcompacttable\">pgcompacttable<\/a><\/noindex> sind Drittanbieter-Utilities zur Komprimierung von Tabellen. Und sie gehen behutsamer mit der Datenbank um. <\/p>\n<p><\/p>\n<p>Sie werden je nach Ihrer Bequemlichkeit verwendet. Aber dazu werde ich am Ende mehr sagen. Wichtig ist, dass es drei Werkzeuge gibt. Es gibt genug Auswahl. <\/p>\n<p><\/p>\n<p>Nachdem wir alles korrigiert haben und sichergestellt haben, dass alles gut geworden ist, m\u00fcssen wir wissen, wie wir diese Situation in Zukunft vermeiden k\u00f6nnen:<\/p>\n<p><\/p>\n<ul>\n<li>Das kann relativ einfach verhindert werden. Man muss die Dauer der Sitzungen auf dem Master-Server \u00fcberwachen. <strong>Besonders gef\u00e4hrlich sind Sitzungen im Status idle in transaction.<\/strong>Das sind die, die gerade eine Transaktion ge\u00f6ffnet haben, etwas gemacht haben und dann weggegangen sind oder einfach h\u00e4ngen geblieben sind, verloren im Code. <\/li>\n<li>Und f\u00fcr Sie, als Entwickler, ist es wichtig, den Code in dem Moment zu testen, in dem solche Situationen entstehen. Das ist nicht schwer zu machen. Es wird eine n\u00fctzliche \u00dcberpr\u00fcfung sein. Sie vermeiden eine gro\u00dfe Anzahl von \u201eAnfangs\u201c-Problemen, die mit langen Transaktionen verbunden sind. <\/li>\n<\/ul>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Typische Fehler in Anwendungen, die zu Bloat in PostgreSQL f\u00fchren. Andrey Salnikov\" src=\"\/wp-content\/uploads\/2020\/05\/d55465d96c4018db733954867d23aaba.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Auf diesen Grafiken wollte ich Ihnen zeigen, wie sich die Tabelle und das Verhalten der Datenbank ver\u00e4ndert haben, nachdem ich in diesem Fall mit VACUUM FULL auf die Tabelle zugegriffen habe. Das ist nicht in der Produktion.<\/p>\n<p><\/p>\n<p>Die Gr\u00f6\u00dfe der Tabelle hat sofort wieder einen normalen Arbeitszustand von ein paar Megabyte erreicht. Dies hatte keinen signifikanten Einfluss auf die durchschnittliche Antwortzeit des Servers. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Typische Fehler in Anwendungen, die zu Bloat in PostgreSQL f\u00fchren. Andrey Salnikov\" src=\"\/wp-content\/uploads\/2020\/05\/cbb07ad24dba899395223d1ca25e438e.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Insbesondere bei unserer getesteten Tabelle, in der wir die Best\u00e4nde auf den Konten aktualisiert haben, sehen wir, dass die durchschnittliche Antwortzeit f\u00fcr das Datenaktualisierungsanfrage auf ein sicheres Niveau gesenkt wurde. Auch die vom Prozessor verbrauchten Ressourcen zur Ausf\u00fchrung dieser Anfrage sind auf ein sicheres Niveau gefallen. Und das rechte untere Diagramm zeigt, dass wir jetzt genau die Zeile finden, die wir ben\u00f6tigen, ohne durch die Sammlung toter Zeilen zu gehen, die vor der Kompression der Tabelle existierte. Die durchschnittliche Anfragenzeit blieb ungef\u00e4hr auf demselben Niveau. Aber hier ist wohl eher eine Ungenauigkeit meiner Hardware.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Typische Fehler in Anwendungen, die zu Bloat in PostgreSQL f\u00fchren. Andrey Salnikov\" src=\"\/wp-content\/uploads\/2020\/05\/c1d90c5442e02fce209dc40e048a8ca2.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Damit endet die erste Geschichte. Sie ist die h\u00e4ufigste und passiert jedem, unabh\u00e4ngig von der Erfahrung des Kunden oder der Qualifikation der Programmierer. Fr\u00fcher oder sp\u00e4ter geschieht das. <\/p>\n<p><\/p>\n<p>Die zweite Geschichte, in der wir die Last verteilen und die Serverressourcen optimieren.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Typische Fehler in Anwendungen, die zu Bloat in PostgreSQL f\u00fchren. Andrey Salnikov\" src=\"\/wp-content\/uploads\/2020\/05\/cda421c554d1329107ddc935045cc1b9.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<ul>\n<li>Wir sind bereits gewachsen und zu ernsthaften Akteuren geworden. Und wir verstehen, dass wir eine Replikation haben und es gut w\u00e4re, die Last zu balancieren: Schreiben auf den Master und Lesen von der Replikation. Diese Situation entsteht normalerweise, wenn wir Berichte oder ETL-Operationen erstellen m\u00f6chten. Das erfreut das Gesch\u00e4ft sehr. Es m\u00f6chte viele unterschiedliche Berichte mit einer Menge komplexer Analysen. <\/li>\n<li>Die Berichte dauern viele Stunden, denn komplexe Analysen lassen sich nicht in Millisekunden berechnen. Wir, als mutige Typen, schreiben den Code. Wir machen in der Anwendung Einf\u00fcgungen, damit wir auf den Master schreiben und die Berichte auf der Replikation ausf\u00fchren. <\/li>\n<li>Wir verteilen die Last. <\/li>\n<li>Alles funktioniert hervorragend. Wir sind gut. <\/li>\n<\/ul>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Typische Fehler in Anwendungen, die zu Bloat in PostgreSQL f\u00fchren. Andrey Salnikov\" src=\"\/wp-content\/uploads\/2020\/05\/e94c8c492197a5015ac8aae79389a4c2.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Wie sieht diese Situation aus? Insbesondere in diesen Grafiken habe ich auch die Dauer der Transaktionen von der Replikation hinzugef\u00fcgt. Alle anderen Grafiken beziehen sich nur auf den Master-Server. <\/p>\n<p><\/p>\n<p>Das Berichtstableau hat sich bis zu diesem Zeitpunkt vergr\u00f6\u00dfert. Es sind mehr Berichte geworden. Wir sehen, dass die durchschnittliche Serverantwortzeit stabil ist. Wir sehen, dass es auf der Replik eine langwierige Transaktion gibt, die seit 2 Stunden l\u00e4uft. Wir beobachten eine ruhige Arbeit des Autovacuum, das tote Zeilen verarbeitet. Und insgesamt l\u00e4uft es gut. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Typische Fehler in Anwendungen, die zu Bloat in PostgreSQL f\u00fchren. Andrey Salnikov\" src=\"\/wp-content\/uploads\/2020\/05\/2da8acf098d12d6f146ab9b9dcb54b81.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Konkret in Bezug auf das getestete Tableau aktualisieren wir weiterhin die Best\u00e4nde auf den Konten. Auch hier haben wir eine stabile Antwortzeit auf die Anfrage und einen stabilen Ressourcenverbrauch. Alles l\u00e4uft gut. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Typische Fehler in Anwendungen, die zu Bloat in PostgreSQL f\u00fchren. Andrey Salnikov\" src=\"\/wp-content\/uploads\/2020\/05\/3621ef723017bac6fb635caf0a5f4de6.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Alles ist gut, bis diese Berichte aufgrund von Konflikten mit der Replikation abgeworfen werden. Und sie werden mit konstanter Regelm\u00e4\u00dfigkeit abgeworfen. <\/p>\n<p><\/p>\n<p>Wir gehen ins Internet und beginnen zu lesen, warum das passiert. Und wir finden eine L\u00f6sung. <\/p>\n<p><\/p>\n<p>Die erste L\u00f6sung besteht darin, die Replikationsverz\u00f6gerung zu erh\u00f6hen. Wir wissen, dass unser Bericht 3 Stunden l\u00e4uft. Wir setzen die Replikationsverz\u00f6gerung auf 3 Stunden. Wir starten alles, aber trotzdem haben wir weiterhin Probleme damit, dass Berichte manchmal abgeworfen werden. <\/p>\n<p><\/p>\n<p>Wir m\u00f6chten, dass alles perfekt ist. Daher suchen wir weiter. Und wir finden eine gro\u00dfartige Einstellung im Internet - hot_standby_feedback. Wir aktivieren sie. Hot_standby_feedback erm\u00f6glicht es uns, die Arbeit des Autovacuum auf dem Master zu halten. Dadurch vermeiden wir vollst\u00e4ndig die Replikationskonflikte. Und alles funktioniert gut mit den Berichten.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Typische Fehler in Anwendungen, die zu Bloat in PostgreSQL f\u00fchren. Andrey Salnikov\" src=\"\/wp-content\/uploads\/2020\/05\/ee3c315168bdd3f392d2e8a1c5861004.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Was geschieht zu diesem Zeitpunkt mit dem Master-Server? Mit dem Master-Server geschieht ein totales Desaster. Jetzt beobachten wir die Grafiken, seit ich beide Einstellungen aktiviert habe. Und wir sehen, dass die Sitzung auf der Replikelle irgendwie die Situation auf dem Master-Server beeinflusst hat. Sie hat tats\u00e4chlich einen Einfluss, da sie das Autovacuum, das tote Zeilen aufr\u00e4umt, angehalten hat. Die Tabellen Gr\u00f6\u00dfe ist wieder in die H\u00f6he geschossen. Die durchschnittliche Abfragezeit in der gesamten Datenbank ist ebenfalls in die H\u00f6he geschossen. Die Autovacuum-Prozesse haben sich ein wenig angestrengt. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Typische Fehler in Anwendungen, die zu Bloat in PostgreSQL f\u00fchren. Andrey Salnikov\" src=\"\/wp-content\/uploads\/2020\/05\/980611dcce8b189dc50f422ffd3d2d72.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Konkret f\u00fcr unser Tableau sehen wir, dass die Aktualisierungen der Daten auch eine enorme Steigerung erfahren haben. Der Ressourcenverbrauch der CPU hat sich ebenfalls stark erh\u00f6ht. Wir durchforsten wieder eine gro\u00dfe Anzahl toter, nutzloser Zeilen. Und die Antwortzeit f\u00fcr dieses Tableau, die Anzahl der Transaktionen ist gesunken. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Typische Fehler in Anwendungen, die zu Bloat in PostgreSQL f\u00fchren. Andrey Salnikov\" src=\"\/wp-content\/uploads\/2020\/05\/a648fd313a5dccf45f0056dc13c54263.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Wie w\u00fcrde das aussehen, wenn wir nicht w\u00fcssten, wor\u00fcber ich bis jetzt gesprochen habe?<\/p>\n<p><\/p>\n<ul>\n<li>Wir beginnen, Probleme zu suchen. Wenn wir in der ersten Phase auf Probleme gesto\u00dfen sind, wissen wir, dass dies an einer langen Transaktion liegen kann und wir uns am Master herumschlagen. Das Problem liegt bei uns am Master. Es schwankt. Er wird hei\u00df, seine Lastdurchschnitt liegt unter hundert. <\/li>\n<li>Die Anfragen dort sind langsam, aber wir sehen keine langen Transaktionen. Und wir verstehen nicht, worum es geht. Wir wissen nicht, wo wir suchen sollen. <\/li>\n<li>Wir \u00fcberpr\u00fcfen die Serverhardware. Vielleicht ist unser RAID ausgefallen. Vielleicht ist ein RAM-Riegel defekt. Es kann alles M\u00f6gliche sein. Aber nein, die Server sind neu, alles funktioniert einwandfrei. <\/li>\n<li>Alle sind unterwegs: Administratoren, Entwickler und der Direktor. Nichts hilft. <\/li>\n<li>Und irgendwann beginnt sich alles pl\u00f6tzlich von selbst zu stabilisieren. <\/li>\n<\/ul>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Typische Fehler in Anwendungen, die zu Bloat in PostgreSQL f\u00fchren. Andrey Salnikov\" src=\"\/wp-content\/uploads\/2020\/05\/7d4f6417bc5cb3cec33679d843c6661d.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>An der Replica hat in der Zwischenzeit eine Anfrage bearbeitet und ist verschwunden. Wir haben den Bericht erhalten. Das Gesch\u00e4ft ist immer noch zufrieden. Wie wir sehen, ist die Tabelle wieder gewachsen und zeigt keine Anzeichen, kleiner zu werden. In dem Diagramm mit den Sitzungen habe ich einen Ausschnitt von dieser langen Transaktion von der Replica gelassen, damit Sie einsch\u00e4tzen k\u00f6nnen, wie lange es dauert, bis die Situation stabilisiert ist. <\/p>\n<p><\/p>\n<p>Die Sitzung ist abgebrochen. Und erst nach einer Weile kommt der Server einigerma\u00dfen in Ordnung. Und die durchschnittliche Antwortzeit der Anfragen am Master-Server normalisiert sich. Denn endlich hat der Autovacuum die M\u00f6glichkeit bekommen, diese toten Zeilen zu bereinigen und zu markieren. Und er hat begonnen, seine Arbeit zu verrichten. Und so schnell er das tut, desto schneller kommen wir wieder in Ordnung.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Typische Fehler in Anwendungen, die zu Bloat in PostgreSQL f\u00fchren. Andrey Salnikov\" src=\"\/wp-content\/uploads\/2020\/05\/547d195e08de1566da818150a47218eb.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>An der getesteten Tabelle, in der wir die Kontost\u00e4nde aktualisieren, sehen wir genau dasselbe Bild. Die durchschnittliche Zeit f\u00fcr die Aktualisierung des Kontos normalisiert sich ebenfalls allm\u00e4hlich. Der Ressourcenverbrauch durch die CPU nimmt ebenfalls ab. Und die Anzahl der Transaktionen pro Sekunde kehrt zur Normalit\u00e4t zur\u00fcck. Aber erneut nicht zu dem Niveau, das wir vor dem Vorfall hatten. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Typische Fehler in Anwendungen, die zu Bloat in PostgreSQL f\u00fchren. Andrey Salnikov\" src=\"\/wp-content\/uploads\/2020\/05\/29372a5e9124690931485a7aea65befc.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Wir stellen in jedem Fall eine Leistungseinbu\u00dfe von anderthalb bis zwei Mal fest, manchmal sogar mehr. <\/p>\n<p><\/p>\n<p>Wir haben scheinbar alles richtig gemacht. Die Last verteilt. Die Hardware steht nicht still. Wir haben die Anfragen sinnvoll aufgeteilt, aber dennoch ist alles schlecht gelaufen. <\/p>\n<p><\/p>\n<ul>\n<li>Hot_standby_feedback nicht aktivieren? Ja, es wird nicht empfohlen, dies ohne besonders starke Gr\u00fcnde zu aktivieren. Denn dieses Feature hat direkten Einfluss auf den Master-Server und unterbricht die Arbeit des Auto-Vakuums dort. Wenn Sie es auf einer bestimmten Replik aktivieren und vergessen, k\u00f6nnen Sie den Master gef\u00e4hrden und ernsthafte Probleme mit der Anwendung bekommen. <\/li>\n<li>Max_standby_streaming_delay erh\u00f6hen? Ja, das ist korrekt bei Berichten. Wenn Sie einen dreist\u00fcndigen Bericht haben und nicht wollen, dass er aufgrund von Replikationskonflikten fehlschl\u00e4gt, erh\u00f6hen Sie einfach die Verz\u00f6gerung. Ein langwieriger Bericht ben\u00f6tigt niemals Daten, die gerade jetzt in der Datenbank angekommen sind. Wenn es sich um einen dreist\u00fcndigen Bericht handelt, bedeutet das, dass Sie ihn f\u00fcr einen \u00e4lteren Datenzeitraum starten. Und ob es drei oder sechs Stunden Verz\u00f6gerung sind, spielt keine Rolle, aber so erhalten Sie Ihre Berichte stabil und haben keine Probleme mit deren Ausfall. <\/li>\n<li>Nat\u00fcrlich m\u00fcssen lange Sessions auf den Replikaten \u00fcberwacht werden, insbesondere wenn Sie beschlossen haben, hot_standby_feedback auf dem Replikat zu aktivieren. Denn es kann passieren, was auch immer. Sie haben dieses Replikat einem Entwickler zur Verf\u00fcgung gestellt, damit er Abfragen testen kann. Er hat eine verr\u00fcckte Abfrage geschrieben, sie gestartet und ist zum Tee gegangen, w\u00e4hrend wir einen \u00fcberlasteten Master bekommen haben. Oder wir haben dort eine falsche Anwendung laufen lassen. Die Situationen sind vielf\u00e4ltig. Sessions auf den Replikaten m\u00fcssen ebenso sorgf\u00e4ltig kontrolliert werden wie auf dem Master. <\/li>\n<li>Wenn Sie also schnelle und langwierige Abfragen auf den Replikaten haben, dann ist es in diesem Fall besser, diese zur Lastverteilung zu splitten. Dies h\u00e4ngt mit dem streaming_delay zusammen. F\u00fcr schnelle Abfragen haben Sie ein Replikat mit kurzer Replikationsverz\u00f6gerung. F\u00fcr langwierige Berichtsabfragen haben Sie ein Replikat, das bis zu 6 Stunden oder einen Tag im R\u00fcckstand sein kann. Das ist eine ganz normale Situation. <\/li>\n<\/ul>\n<p><\/p>\n<p>Die Folgen beseitigen wir auf die gleiche Weise:<\/p>\n<p><\/p>\n<ul>\n<li>Wir finden aufgebl\u00e4hte Tabellen.<\/li>\n<li>Und wir komprimieren sie mit dem f\u00fcr uns passendsten Werkzeug. <\/li>\n<\/ul>\n<p><\/p>\n<p>Die zweite Geschichte endet hier. Wir kommen zur dritten Geschichte. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Typische Fehler in Anwendungen, die zu Bloat in PostgreSQL f\u00fchren. Andrey Salnikov\" src=\"\/wp-content\/uploads\/2020\/05\/c8784e0be27883640cb8f6919a1c25e0.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Ebenfalls ziemlich gew\u00f6hnlich f\u00fcr uns, in der wir eine Migration durchf\u00fchren. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Typische Fehler in Anwendungen, die zu Bloat in PostgreSQL f\u00fchren. Andrey Salnikov\" src=\"\/wp-content\/uploads\/2020\/05\/a04b9cd88a0e7e8a3b960ef930eb2657.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<ul>\n<li>Jedes Softwareprodukt w\u00e4chst. Die Anforderungen daran \u00e4ndern sich. Wir wollen uns in jedem Fall weiterentwickeln. Und manchmal ist es notwendig, die Daten in der Tabelle zu aktualisieren, das hei\u00dft, ein Update im Rahmen unserer Migration f\u00fcr neue Funktionen, die wir im Rahmen unserer Weiterentwicklung einf\u00fchren. <\/li>\n<li>Das alte Datenformat ist nicht zufriedenstellend. Angenommen, wir wenden uns jetzt der zweiten Tabelle zu, in der ich die Operationen zu diesen Konten habe. Und nehmen wir an, sie waren in Rubel, und wir haben beschlossen, die Genauigkeit zu erh\u00f6hen und sie in Kopeken zu f\u00fchren. Daf\u00fcr m\u00fcssen wir ein Update durchf\u00fchren: das Feld mit dem Betrag der Operation mit hundert multiplizieren. <\/li>\n<li>In der modernen Welt nutzen wir automatisierte Mittel zur Versionskontrolle von Datenbanken. Angenommen, <noindex><a rel=\"nofollow\" href=\"https:\/\/www.liquibase.org\/\">Liquibase<\/a><\/noindex>. Wir schreiben dort unsere Migration. Testen sie auf unserer Testdatenbank. Alles funktioniert hervorragend. Das Update verl\u00e4uft erfolgreich. Es blockiert die Arbeit f\u00fcr eine gewisse Zeit, aber daf\u00fcr erhalten wir aktualisierte Daten. Und wir k\u00f6nnen die neue Funktionalit\u00e4t darauf aufbauen. Alles getestet, \u00fcberpr\u00fcft. Alles best\u00e4tigt. <\/li>\n<li>Wir haben planm\u00e4\u00dfige Arbeiten durchgef\u00fchrt und die Migration abgeschlossen. <\/li>\n<\/ul>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Typische Fehler in Anwendungen, die zu Bloat in PostgreSQL f\u00fchren. Andrey Salnikov\" src=\"\/wp-content\/uploads\/2020\/05\/9e046583f7b1723fc1eaf61a03900918.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Hier ist die Migration mit dem Update, die Ihnen pr\u00e4sentiert wird. Da es sich um meine Operationen zu den Konten handelt, war die Tabelle 15 GB gro\u00df. Und da wir jede Zeile aktualisieren, haben wir die Tabelle durch das Update verdoppelt, weil wir jede Zeile \u00fcberschrieben haben. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Typische Fehler in Anwendungen, die zu Bloat in PostgreSQL f\u00fchren. Andrey Salnikov\" src=\"\/wp-content\/uploads\/2020\/05\/06120c98ea43d0568045e71935c23592.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>W\u00e4hrend der Migration konnten wir mit dieser Tabelle nichts tun, da alle Abfragen an sie in die Warteschlange gestellt wurden und darauf warteten, dass dieses Update abgeschlossen ist. Aber ich m\u00f6chte Ihre Aufmerksamkeit auf die Zahlen auf der vertikalen Achse lenken. Das hei\u00dft, wir haben eine durchschnittliche Abfragezeit vor der Migration von etwa 5 Millisekunden und die CPU-Belastung, die Anzahl der blockierenden Lesevorg\u00e4nge im Festplattenspeicher, liegt unter 7,5. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Typische Fehler in Anwendungen, die zu Bloat in PostgreSQL f\u00fchren. Andrey Salnikov\" src=\"\/wp-content\/uploads\/2020\/05\/69a3ba4d1d0cec7d39284e09e9d3055b.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Die Migration wurde durchgef\u00fchrt und wir haben erneut Probleme erhalten. <\/p>\n<p><\/p>\n<p>Die Migration war erfolgreich, aber:<\/p>\n<p><\/p>\n<ul>\n<li>Die alte Funktionalit\u00e4t ben\u00f6tigt jetzt l\u00e4nger. <\/li>\n<li>Die Tabelle ist erneut gewachsen. <\/li>\n<li>Die Last auf dem Server ist erneut h\u00f6her geworden als zuvor. <\/li>\n<li>Und nat\u00fcrlich besch\u00e4ftigen wir uns noch mit der Funktionalit\u00e4t, die gut funktionierte; wir haben sie ein wenig verbessert. <\/li>\n<\/ul>\n<p><\/p>\n<p>Und das ist erneut Bloat, der uns wieder das Leben schwer macht. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Typische Fehler in Anwendungen, die zu Bloat in PostgreSQL f\u00fchren. Andrey Salnikov\" src=\"\/wp-content\/uploads\/2020\/05\/becd7cce3a1c8821c81c96257f41202b.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Hier demonstriere ich, dass die Tabelle, wie in den vorherigen beiden F\u00e4llen, nicht plant, zu den vorherigen Gr\u00f6\u00dfen zur\u00fcckzukehren. Die durchschnittliche Serverlast scheint jedoch angemessen zu sein. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Typische Fehler in Anwendungen, die zu Bloat in PostgreSQL f\u00fchren. Andrey Salnikov\" src=\"\/wp-content\/uploads\/2020\/05\/4d703a60d43a3460bc3782d49865b690.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Wenn wir uns die Tabelle mit den Rechnungen ansehen, stellen wir fest, dass die durchschnittliche Abfragezeit zu dieser Tabelle sich verdoppelt hat. Die Auslastung des Prozessors und die Anzahl der im Speicher durchsuchten Zeilen sind auf \u00fcber 7,5 gestiegen, w\u00e4hrend sie zuvor darunter lag. Bei den Prozessoren hat sich dieser Wert verdoppelt, bei den blockweisen Operationen um das 1,5-fache, das hei\u00dft, wir haben eine Leistungsdegradation des Servers erlebt. Folglich f\u00fchrte dies zu einer Verschlechterung der Leistung unserer Anwendung. Die Anzahl der Aufrufe blieb etwa auf demselben Niveau. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Typische Fehler in Anwendungen, die zu Bloat in PostgreSQL f\u00fchren. Andrey Salnikov\" src=\"\/wp-content\/uploads\/2020\/05\/80772afa0643b29f5314a2482c9dfe0d.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Dabei ist es wichtig zu verstehen, wie man solche Migrationen richtig durchf\u00fchrt. Und es ist notwendig, sie durchzuf\u00fchren. Wir f\u00fchren diese Migrationen ziemlich regelm\u00e4\u00dfig durch.<\/p>\n<p><\/p>\n<ul>\n<li>Solche gro\u00dfen Migrationen erfolgen nicht automatisch. Sie sollten immer kontrolliert werden. <\/li>\n<li>Es ist notwendig, dass eine sachkundige Person die Kontrolle hat. Wenn Sie einen DBA im Team haben, sollte dieser die Migration durchf\u00fchren. Das ist seine Aufgabe. Wenn nicht, sollte die erfahrenste Person im Team dies tun, die wei\u00df, wie man mit Datenbanken arbeitet. <\/li>\n<li>Das neue Datenbankschema, selbst wenn wir nur eine Spalte aktualisieren, wird immer schrittweise vorbereitet, d. h. vor der Ver\u00f6ffentlichung der neuen Version der Anwendung:<\/li>\n<li>Neue Felder werden hinzugef\u00fcgt, in die wir die aktualisierten Daten schreiben werden. <\/li>\n<li>Wir \u00fcbertragen die Daten aus dem alten Feld in das neue Feld in kleinen Teilen. Warum tun wir das? Erstens kontrollieren wir immer den Prozess dieser \u00dcbertragung. Wir wissen, dass wir bereits so und so viele Batch-\u00dcbertragungen durchgef\u00fchrt haben und noch so viel \u00fcbrig ist. <\/li>\n<li>Der zweite positive Effekt besteht darin, dass wir zwischen jedem Batch die Transaktion schlie\u00dfen, eine neue er\u00f6ffnen und dies dem Auto-Vakuum erm\u00f6glicht, an der Tabelle zu arbeiten und die toten Zeilen zur Wiederverwendung zu markieren. <\/li>\n<li>F\u00fcr die Zeilen, die w\u00e4hrend der Arbeit der Anwendung entstehen (unsere alte Anwendung l\u00e4uft noch), f\u00fcgen wir einen Trigger hinzu, der neue Werte in die neuen Felder schreibt. In unserem Fall ist das das alte Wertes multipliziert mit hundert. <\/li>\n<li>Wenn wir ganz stur sind und das gleiche Feld wollen, benennen wir nach Abschluss aller Migrationen und vor der Einf\u00fchrung der neuen Version der Anwendung einfach die Felder um. Die alten in einen beliebigen erfundenen Namen und die neuen Felder in die alten. <\/li>\n<li>Und erst danach starten wir die neue Version der Anwendung. <\/li>\n<\/ul>\n<p><\/p>\n<p>Dabei werden wir kein Bloat erhalten und nicht an Leistung verlieren. <\/p>\n<p><\/p>\n<p>Damit endete die dritte Geschichte. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Typische Fehler in Anwendungen, die zu Bloat in PostgreSQL f\u00fchren. Andrey 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>Und jetzt ein bisschen detaillierter \u00fcber die Werkzeuge, die ich in der allerersten Geschichte erw\u00e4hnt habe. <\/p>\n<p><\/p>\n<p>Bevor Sie nach Bloat suchen, sollten Sie unbedingt die Erweiterung installieren. <noindex><a rel=\"nofollow\" href=\"https:\/\/www.postgresql.org\/docs\/current\/pgstattuple.html\">pgstattuple<\/a><\/noindex>.<\/p>\n<p><\/p>\n<p>Damit Sie keine Anfragen erfinden m\u00fcssen, haben wir in unserer Arbeit bereits diese Anfragen geschrieben. Sie k\u00f6nnen sie verwenden. Hier werden zwei Anfragen pr\u00e4sentiert. <\/p>\n<p><\/p>\n<ul>\n<li>Die erste arbeitet recht lange, aber daf\u00fcr zeigt sie Ihnen die genauen Werte des Bloats in der Tabelle. <\/li>\n<li>Die zweite funktioniert schneller und ist sehr effektiv, wenn Sie schnell einsch\u00e4tzen m\u00fcssen \u2013 gibt es Bloat oder nicht in der Tabelle. Und Sie sollten auch verstehen, dass Bloat in einer Postgres-Tabelle immer vorhanden ist. Das ist eine Besonderheit seines MVCC-Modells. <\/li>\n<li>Und 20 % Bloat sind in den meisten F\u00e4llen f\u00fcr Tabellen normal. Das hei\u00dft, Sie m\u00fcssen sich keine Sorgen machen und diese Tabelle komprimieren. <\/li>\n<\/ul>\n<p><\/p>\n<p>Wie wir Tabellen identifizieren, die angeschwollen sind, haben wir verstanden, insbesondere wenn sie mit nutzlosen Daten angeschwollen sind. <\/p>\n<p><\/p>\n<p>Jetzt zu dem, wie man Bloat behebt:<\/p>\n<p><\/p>\n<ul>\n<li>Wenn wir eine kleine Tabelle haben und gute Festplatten, d. h. bei einer Tabelle bis zu einem Gigabyte, kann man VACUUM FULL durchaus verwenden. Es wird f\u00fcr einige Sekunden eine exklusive Sperre auf die Tabelle nehmen und das ist in Ordnung, denn es erledigt alles schnell und gr\u00fcndlich. Was macht VACUUM FULL? Es nimmt eine exklusive Sperre auf die Tabelle und schreibt aktive Zeilen aus alten Tabellen in die neue Tabelle. Am Ende tauscht es sie aus. Alte Dateien werden gel\u00f6scht, neue werden an deren Stelle gesetzt. Aber w\u00e4hrend seiner Arbeit nimmt es eine exklusive Sperre auf die Tabelle. Das bedeutet, dass Sie mit dieser Tabelle nichts machen k\u00f6nnen: Sie k\u00f6nnen nicht in sie schreiben, nicht von ihr lesen und sie nicht modifizieren. Au\u00dferdem ben\u00f6tigt VACUUM FULL zus\u00e4tzlichen Speicherplatz auf der Festplatte, um die Daten zu speichern.<\/li>\n<li>Das n\u00e4chste Tool <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/reorg\/pg_repack\">pg_repack<\/a><\/noindex>: Nach seinem Prinzip ist es VACUUM FULL sehr \u00e4hnlich, da es ebenfalls Daten von alten Dateien in neue neu schreibt und sie in der Tabelle ersetzt. Dabei nimmt es jedoch zu Beginn seiner Arbeit keine exklusive Sperre auf die Tabelle, sondern nur im Moment, wenn es bereits fertige Daten hat, um die Dateien auszutauschen. Die Anforderungen an die Festplattenspeicher sind \u00e4hnlich wie bei VACUUM FULL. Sie ben\u00f6tigen zus\u00e4tzlichen Speicherplatz auf der Festplatte, und das kann manchmal kritisch sein, wenn Sie Terabyte-Tabellen haben. Und es ist ziemlich rechenintensiv, da es aktiv mit Ein-\/Ausgabe arbeitet. <\/li>\n<li>Das dritte Tool ist <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/dataegret\/pgcompacttable\">pgcompacttable<\/a><\/noindex>. Sie geht sorgsamer mit den Ressourcen um, weil sie nach etwas anderen Prinzipien arbeitet. Das Hauptziel von pgcompacttable ist es, durch Updates alle lebenden Zeilen an den Anfang der Tabelle zu verschieben. Danach wird der Vacuum-Prozess f\u00fcr diese Tabelle gestartet, da wir wissen, dass am Anfang die lebenden und am Ende die toten Zeilen sind. Und der Vacuum-Prozess schneidet diesen \u201eSchwanz\u201c ab, das hei\u00dft, er ben\u00f6tigt nicht viel zus\u00e4tzlichen Speicherplatz. Gleichzeitig kann er auch ressourcenschonend sein. <\/li>\n<\/ul>\n<p><\/p>\n<p>Mit den Werkzeugen ist alles. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Typische Fehler in Anwendungen, die zu Bloat in PostgreSQL f\u00fchren. Andrey Salnikov\" src=\"\/wp-content\/uploads\/2020\/05\/4187915e54e54a0b85a342fe0280f78f.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Wenn Ihnen das Thema Bloat interessant erscheint, um weiter einzutauchen, hier einige n\u00fctzliche Links:<\/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 das ist der Vortrag meines Kollegen. Er gibt einen allgemeinen \u00dcberblick dar\u00fcber, wo der Speicherplatz bei Postgres im Laufe seiner Nutzung bleibt. Und dort findet sich ein gro\u00dfer und detaillierter technischer Abschnitt f\u00fcr Datenbankadministratoren \u00fcber Bloat. <\/li>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/dataegret\/pg-utils\">https:\/\/github.com\/dataegret\/pg-utils<\/a><\/noindex> \u2013 das ist ein Link zu unserem Repository, in dem wir eine Menge n\u00fctzlicher Skripte zur \u00dcberpr\u00fcfung des Datenbankzustands speichern. Dort finden Sie Skripte zur Suche nach Bloat. <\/li>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/reorg\/pg_repack\">Dritte<\/a><\/noindex> und <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/dataegret\/pgcompacttable\">vierte<\/a><\/noindex> Links zu Werkzeugen, die Ihnen helfen, Tabellen zu verkleinern. <\/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 das ist ein Beitrag meines Kollegen. Dort wird Bloat recht umfangreich und detailliert behandelt, insbesondere auf einer Ebene, die f\u00fcr Administratoren relevant ist. <\/li>\n<\/ul>\n<p><\/p>\n<p>Hier habe ich versucht, eine Warnung f\u00fcr die Entwickler darzustellen, da sie unsere direkten Kunden im Datenbankbereich sind und verstehen m\u00fcssen, welche Handlungen welche Folgen haben. Ich hoffe, das ist mir gelungen. Vielen Dank f\u00fcr Ihre Aufmerksamkeit!<\/p>\n<p><\/p>\n<p>Fragen<\/p>\n<p><\/p>\n<p><em>Danke f\u00fcr den Vortrag! Sie haben dar\u00fcber gesprochen, wie man Probleme identifizieren kann. Wie k\u00f6nnen sie pr\u00e4ventiv vermieden werden? Ich hatte eine Situation, in der Anfragen nicht nur wegen der Anbindung an externe Dienste hingen. Es waren einfach einige wilde Joins. Es gab harmlose, winzige Anfragen, die einen Tag lang hingen und dann anfingen, seltsame Dinge zu verursachen. Das sieht sehr \u00e4hnlich aus wie das, was Sie beschrieben haben. Wie verfolgt man das? Soll man st\u00e4ndig beobachten, welche Anfrage h\u00e4ngt? Wie kann man das verhindern?<\/em><\/p>\n<p><\/p>\n<p>In diesem Fall ist es die Aufgabe der Administratoren Ihres Unternehmens, nicht unbedingt der DBA.<\/p>\n<p><\/p>\n<p><em>Ich bin Administrator.<\/em><\/p>\n<p><\/p>\n<p>In PostgreSQL gibt es die Ansicht pg_stat_activity, in der die h\u00e4ngenden Anfragen angezeigt werden. Dort k\u00f6nnen Sie sehen, wie lange sie dort h\u00e4ngen.<\/p>\n<p><\/p>\n<p><em>Muss ich alle 5 Minuten nachschauen?<\/em><\/p>\n<p><\/p>\n<p>Stellen Sie den Cron ein und \u00fcberpr\u00fcfen Sie. Wenn Sie eine langwierige Anfrage haben, schreiben Sie eine E-Mail und das war's. Das hei\u00dft, Sie m\u00fcssen nicht selbst nachsehen, das kann automatisiert werden. Sie erhalten eine E-Mail, auf die Sie reagieren. Sie k\u00f6nnen auch automatisch antworten.<\/p>\n<p><\/p>\n<p><em>Gibt es offensichtliche Gr\u00fcnde, warum das passiert?<\/em><\/p>\n<p><\/p>\n<p>Ich habe einige aufgez\u00e4hlt. Andere komplexere Beispiele. Und das Gespr\u00e4ch kann lange dauern.<\/p>\n<p><\/p>\n<p><em>Danke f\u00fcr den Bericht! Ich wollte zur pg_repack-Utility nachfragen. Wenn sie keine exklusive Sperre vornimmt, dann\u2026<\/em><\/p>\n<p><\/p>\n<p>Sie nimmt eine exklusive Sperre vor. <\/p>\n<p><\/p>\n<p>\u2026 <em>dann kann ich potenziell Daten verlieren. Mein Programm sollte zu diesem Zeitpunkt nichts aufschreiben?<\/em><\/p>\n<p><\/p>\n<p>Nein, es arbeitet ruhig mit der Tabelle, das hei\u00dft, pg_repack verschiebt zuerst alle aktiven Zeilen, die vorhanden sind. Nat\u00fcrlich erfolgt dort irgendein Schreibvorgang in die Tabelle. Er f\u00fcgt einfach diesen kleinen Rest hinzu. <\/p>\n<p><\/p>\n<p><em>Das hei\u00dft, tut er am Ende doch?<\/em><\/p>\n<p><\/p>\n<p>Am Ende nimmt er die exklusive Sperre, um diese Dateien auszutauschen. <\/p>\n<p><\/p>\n<p><em>Wird das schneller sein als VACUUM FULL?<\/em><\/p>\n<p><\/p>\n<p>VACUUM FULL, sobald es gestartet wird, nimmt sofort eine exklusive Sperre. Und solange es nicht fertig ist, l\u00e4sst es sie nicht los. pg_repack hingegen nimmt eine exklusive Sperre nur f\u00fcr den Moment des Date tauschs. In diesem Moment k\u00f6nnen Sie dort nichts aufzeichnen, aber die Daten gehen nicht verloren, alles wird in Ordnung sein. <\/p>\n<p><\/p>\n<p><em>Hallo! Sie haben \u00fcber die Arbeit des Autovacuum gesprochen. Es gab ein Diagramm mit roten, gelben und gr\u00fcnen Aufnahmezellen. Das hei\u00dft, die gelben wurden als gel\u00f6scht markiert. Und daher k\u00f6nnen wir neue Daten dort einf\u00fcgen?<\/em><\/p>\n<p><\/p>\n<p>Ja. Postgres l\u00f6scht keine Zeilen. Es hat diese Spezifik. Wenn wir eine Zeile aktualisieren, markieren wir die alte als gel\u00f6scht. Es wird die ID der Transaktion eingef\u00fcgt, die diese Zeile ge\u00e4ndert hat, und wir schreiben die neue Zeile. Und wir haben Sitzungen, die sie potenziell lesen k\u00f6nnen. Irgendwann werden sie ganz alt. Und die Idee des Autovacuum ist, dass es \u00fcber diese Zeilen l\u00e4uft und sie als nicht mehr ben\u00f6tigt markiert. Und an dieser Stelle k\u00f6nnen wir die Daten \u00fcberschreiben. <\/p>\n<p><\/p>\n<p><em>Ich verstehe. Aber die Frage ist ein bisschen anders. Ich habe noch nicht fertig gesprochen. Angenommen, wir haben eine Tabelle. Diese enth\u00e4lt Felder variabler Gr\u00f6\u00dfe. Und wenn ich versuche, etwas Neues einzuf\u00fcgen, k\u00f6nnte es einfach nicht in die alte Zelle passen.<\/em> <\/p>\n<p><\/p>\n<p>Nein, dort wird in jedem Fall die gesamte Zeile aktualisiert. In Postgres gibt es zwei Modelle zur Datenspeicherung. Es h\u00e4ngt vom Datentyp ab. Es gibt Daten, die direkt in der Tabelle gespeichert werden, und es gibt auch tos-Daten. Das sind gro\u00dfe Datenvolumen: Text, JSON. Sie werden in separaten Tabellen gespeichert. Und in diesen Tabellen passiert die gleiche Geschichte mit Bloat, d.h. alles ist gleich. Nur sind sie separat ausgegliedert. <\/p>\n<p><\/p>\n<p><em>Danke f\u00fcr den Vortrag! Wie akzeptabel ist es, um die Dauer von Abfragen den Statement Timeout zu verwenden?<\/em><\/p>\n<p><\/p>\n<p>Sehr akzeptabel. Wir verwenden das \u00fcberall. Da wir keine eigenen Services haben und Unterst\u00fctzung aus der Ferne leisten, gibt es recht unterschiedliche Kunden. Und alle sind damit recht zufrieden. D.h. wir haben cron-Jobs, die \u00fcberpr\u00fcfen. Einfach wird mit dem Kunden die Dauer der Sitzungen vereinbart, vor der wir nicht abbrechen. Das kann eine Minute oder auch 10 Minuten sein. Das h\u00e4ngt von der Belastung der Datenbank und ihrem Ziel ab. Aber \u00fcberall verwenden wir pg_stat_activity.<\/p>\n<p><\/p>\n<p><em>Danke f\u00fcr den Vortrag! Ich versuche, Ihren Vortrag auf meine Anwendungen anzuwenden. Und anscheinend starten wir \u00fcberall eine Transaktion und beenden sie \u00fcberall explizit. Bei einer Ausnahme findet trotzdem ein Rollback statt. Und da bin ich ins Gr\u00fcbeln gekommen. Denn es kann sein, dass eine Transaktion nicht explizit startet. Das ist wahrscheinlich ein Hinweis f\u00fcr die Dame. Wenn ich einfach einen Datensatz aktualisiere, wird die Transaktion in PostgreSQL gestartet und endet erst, wenn die Verbindung getrennt wird?<\/em><\/p>\n<p><\/p>\n<p>Wenn Sie jetzt \u00fcber die Ebene der Anwendung sprechen, h\u00e4ngt das von dem Treiber ab, den Sie verwenden, und von dem ORM, das verwendet wird. Es gibt viele Einstellungen. Wenn bei Ihnen das Auto-Commit aktiviert ist, wird die Transaktion gestartet und sofort geschlossen.<\/p>\n<p><\/p>\n<p><em>D.h. sie wird sofort nach dem Update geschlossen?<\/em><\/p>\n<p><\/p>\n<p>Das h\u00e4ngt von den Einstellungen ab. Eine Einstellung habe ich genannt. Das ist Auto-Commit. Sie ist recht verbreitet. Wenn sie aktiviert ist, wird die Transaktion ge\u00f6ffnet und geschlossen. Wenn Sie nicht ausdr\u00fccklich \"start transaction\" und \"end transaction\" gesagt haben, sondern einfach die Abfrage in der Sitzung gestartet haben. <\/p>\n<p><\/p>\n<p><em>Hallo! Danke f\u00fcr den Vortrag! Angenommen, wir haben eine Datenbank, die immer gr\u00f6\u00dfer wird und auf dem Server der Platz ausgeht. Gibt es irgendwelche Werkzeuge, um diese Situation zu beheben?<\/em> <\/p>\n<p><\/p>\n<p>Den Platz auf dem Server sollte man idealerweise \u00fcberwachen. <\/p>\n<p><\/p>\n<p><em>Zum Beispiel, der DBA geht Tee trinken, war im Urlaub usw.<\/em><\/p>\n<p><\/p>\n<p>Wenn ein Dateisystem erstellt wird, wird mindestens ein gewisser Reservierungsplatz geschaffen, in den keine Daten geschrieben werden. <\/p>\n<p><\/p>\n<p><em>Und wenn es ganz auf null geht?<\/em><\/p>\n<p><\/p>\n<p>Es wird als reservierter Raum bezeichnet, das hei\u00dft, er kann freigegeben werden, und je nachdem, wie gro\u00df er erstellt wurde, haben Sie freien Speicherplatz erhalten. Ich wei\u00df nicht, wie viel es standardm\u00e4\u00dfig ist. In einem anderen Fall m\u00fcssen Sie Disks beschaffen, damit Sie gen\u00fcgend Platz f\u00fcr den Wiederherstellungsvorgang haben. Sie k\u00f6nnen eine Tabelle l\u00f6schen, die Sie garantiert nicht ben\u00f6tigen. <\/p>\n<p><\/p>\n<p><em>Gibt es keine anderen Werkzeuge?<\/em><\/p>\n<p><\/p>\n<p>Es ist immer Handarbeit. Vor Ort wird festgestellt, was dort am besten zu tun ist, weil es kritische und nicht kritische Daten gibt. Und f\u00fcr jede Datenbank und Anwendung, die damit arbeitet, h\u00e4ngt das vom Gesch\u00e4ft ab. Es wird immer vor Ort entschieden. <\/p>\n<p><\/p>\n<p><em>Danke f\u00fcr den Vortrag! Ich habe zwei Fragen. Erstens, Sie haben Folien gezeigt, auf denen zu sehen war, dass bei h\u00e4ngenden Transaktionen sowohl das Volumen des Tabellenraums als auch die Gr\u00f6\u00dfe des Indexes steigen. Im weiteren Verlauf des Vortrags gab es eine Menge Dienstprogramme, die die Tabelle packen. Und was ist mit dem Index?<\/em><\/p>\n<p><\/p>\n<p>Diese packen sie ebenfalls. <\/p>\n<p><\/p>\n<p><em>Aber der Vacuum-Prozess ber\u00fchrt den Index nicht?<\/em><\/p>\n<p><\/p>\n<p>Einige arbeiten mit dem Index. Zum Beispiel pg_rapack, pgcompacttable. Der Vacuum-Prozess erstellt Indizes neu und betrifft sie. Das Prinzip von VACUUM FULL besteht darin, alles neu zu schreiben, das hei\u00dft, er arbeitet mit allen. <\/p>\n<p><\/p>\n<p><em>Und die zweite Frage. Ich habe nicht verstanden, warum die Berichte auf den Replikaten so stark von der Replikation selbst abh\u00e4ngen. Ich dachte, Berichte sind Lesevorg\u00e4nge und Replikation ist ein Schreibvorgang.<\/em> <\/p>\n<p><\/p>\n<p>Worin besteht der Konflikt bei der Replikation? Wir haben einen Master, auf dem die Prozesse laufen. Es l\u00e4uft ein Auto-Vacuum. Was macht das Auto-Vacuum? Es entfernt einige alte Zeilen. Wenn in dieser Zeit auf dem Replikat eine Anfrage besteht, die diese alten Zeilen liest, und auf dem Master hat das Auto-Vacuum diese Zeilen als potenziell \u00fcberschreibbar markiert, dann haben wir sie \u00fcberschrieben. Und wir haben ein Datenpaket erhalten, wenn wir die Zeilen, die f\u00fcr die Anfrage auf dem Replikat ben\u00f6tigt werden, \u00fcberschreiben m\u00fcssen, dann wartet der Replikationsprozess auf die Timeout-Zeit, die Sie eingestellt haben. Und dann entscheidet PostgreSQL, was f\u00fcr ihn wichtiger ist. Die Replikation ist wichtiger f\u00fcr ihn als die Anfrage, und er wird die Anfrage abbrechen, um diese \u00c4nderungen auf dem Replikat durchzuf\u00fchren. <\/p>\n<p><\/p>\n<p><em>Andrej, ich habe eine Frage. Sind diese wunderbaren Grafiken, die Sie w\u00e4hrend der Pr\u00e4sentation gezeigt haben, das Ergebnis Ihrer Arbeiten, eines Ihrer Tools? Womit wurden die Grafiken erstellt?<\/em><\/p>\n<p><\/p>\n<p>Das ist ein Dienst <noindex><a rel=\"nofollow\" href=\"https:\/\/okmeter.io\/\">Okmeter<\/a><\/noindex>.<\/p>\n<p><\/p>\n<p><em>Ist das ein kommerzielles Produkt?<\/em><\/p>\n<p><\/p>\n<p>Ja. Das ist ein kommerzielles Produkt.<\/p>\n<p>Quelle: <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.1.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\/de\/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.1.1\" \/>\n\t\t<meta property=\"og:locale\" content=\"de_DE\" \/>\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\/de\/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\udd47Typische Fehler in Anwendungen, die zu Bloat in PostgreSQL f\u00fchren. Andrej Salnikow | ProHoster","description":"Ich empfehle, sich mit der Auswertung des Vortrags von Andrej Salnikow aus Anfang 2016 \"Typische Fehler in Anwendungen, die zu Bloat in PostgreSQL f\u00fchren\" vertraut zu machen. In diesem Vortrag werde ich die Grunds\u00e4tze erl\u00e4utern.","canonical_url":"https:\/\/prohoster.info\/de\/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":"de_DE","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\/de\/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\/de\/wp-json\/wp\/v2\/posts\/81089","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/comments?post=81089"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/posts\/81089\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/media\/81090"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/media?parent=81089"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/categories?post=81089"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/tags?post=81089"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}