{"id":30356,"date":"2019-10-31T21:35:06","date_gmt":"2019-10-31T18:35:06","guid":{"rendered":"https:\/\/prohoster.info\/blog\/kak-my-ispolzovali-otlozhennuyu-replikatsiyu-dlya-avarijnogo-vosstanovleniya-s-postgresql\/"},"modified":"2019-10-31T21:35:06","modified_gmt":"2019-10-31T18:35:06","slug":"kak-my-ispolzovali-otlozhennuyu-replikatsiyu-dlya-avarijnogo-vosstanovleniya-s-postgresql","status":"publish","type":"post","link":"https:\/\/prohoster.info\/de\/blog\/administrirovanie\/kak-my-ispolzovali-otlozhennuyu-replikatsiyu-dlya-avarijnogo-vosstanovleniya-s-postgresql","title":{"rendered":"Wie wir verz\u00f6gerte Replikation f\u00fcr die Notfallwiederherstellung mit PostgreSQL eingesetzt haben","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p><img decoding=\"async\" alt=\"Wie wir verz\u00f6gerte Replikation f\u00fcr die Notfallwiederherstellung mit PostgreSQL eingesetzt haben\" src=\"\/wp-content\/uploads\/2019\/03\/773f3b6c8d173be91c49066d7067bad3.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nReplikation ist kein Backup. Oder doch? So haben wir verz\u00f6gerte Replikation zur Wiederherstellung genutzt, nachdem wir versehentlich Shortcuts gel\u00f6scht haben.<\/p>\n<p><\/p>\n<p><noindex><a rel=\"nofollow\" href=\"https:\/\/about.gitlab.com\/handbook\/engineering\/infrastructure\/\">Infrastruktur-Spezialisten<\/a><\/noindex> bei GitLab sind verantwortlich f\u00fcr den Betrieb <noindex><a rel=\"nofollow\" href=\"https:\/\/gitlab.com\/\">GitLab.com<\/a><\/noindex> \u2014 die gr\u00f6\u00dfte Instanz von GitLab weltweit. Hier gibt es 3 Millionen Nutzer und fast 7 Millionen Projekte, und es ist eine der gr\u00f6\u00dften Open-Source-SaaS-Seiten mit dedizierter Architektur. Ohne das PostgreSQL-Datenbanksystem w\u00fcrde die Infrastruktur von GitLab.com nicht weit kommen, und wir tun alles, um die Ausfallsicherheit f\u00fcr den Fall von Datenverlusten zu gew\u00e4hrleisten. Eine solche Katastrophe ist zwar unwahrscheinlich, aber wir sind gut vorbereitet und haben verschiedene Backup- und Replikationsmechanismen eingeplant.<\/p>\n<p><\/p>\n<p>Replikation ist nicht das gleiche wie ein Datenbank-Backup (<noindex><a rel=\"nofollow\" href=\"https:\/\/about.gitlab.com\/2019\/02\/13\/delayed-replication-for-disaster-recovery-with-postgresql\/#summing-up\">siehe unten<\/a><\/noindex>). Aber jetzt werden wir sehen, wie man versehentlich gel\u00f6schte Daten schnell mit verz\u00f6gerter Replikation wiederherstellt: Ich <noindex><a rel=\"nofollow\" href=\"https:\/\/gitlab.com\/\">GitLab.com<\/a><\/noindex> Benutzer <noindex><a rel=\"nofollow\" href=\"https:\/\/gitlab.com\/gitlab-com\/gl-infra\/production\/issues\/509\">habe einen Shortcut gel\u00f6scht<\/a><\/noindex> f\u00fcr das Projekt <noindex><a rel=\"nofollow\" href=\"https:\/\/gitlab.com\/gitlab-org\/gitlab-ce\/\"><code>gitlab-ce<\/code><\/a><\/noindex> und habe die Verbindungen zu Merge-Requests und Aufgaben verloren.<\/p>\n<p><\/p>\n<p>Mit der verz\u00f6gerten Replikation haben wir die Daten in nur 1,5 Stunden wiederhergestellt. Sehen Sie, wie es gemacht wurde.<\/p>\n<p><noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<h3 id=\"vosstanovlenie-na-moment-vremeni-s-postgresql\">Wiederherstellung zu einem bestimmten Zeitpunkt mit PostgreSQL<\/h3>\n<p><\/p>\n<p>PostgreSQL verf\u00fcgt \u00fcber eine integrierte Funktion, die den Zustand der Datenbank zu einem bestimmten Zeitpunkt wiederherstellt. Diese Funktion nennt sich <noindex><a rel=\"nofollow\" href=\"https:\/\/www.postgresql.org\/docs\/current\/continuous-archiving.html\">Point-in-Time Recovery<\/a><\/noindex> (PITR) und nutzt die gleichen Mechanismen, die die Aktualit\u00e4t der Replica unterst\u00fctzen: Ausgehend von einem zuverl\u00e4ssigen Snapshot des gesamten Datenbankclusters (Basis-Backup) wenden wir eine Reihe von Zustands\u00e4nderungen bis zu einem bestimmten Zeitpunkt an.<\/p>\n<p><\/p>\n<p>Um diese Funktion f\u00fcr ein kaltes Backup zu nutzen, f\u00fchren wir regelm\u00e4\u00dfig ein Basis-Backup der Datenbank durch und speichern es im Archiv (GitLab-Archive befinden sich in <noindex><a rel=\"nofollow\" href=\"https:\/\/cloud.google.com\/storage\/\">Google Cloud Storage<\/a><\/noindex>). Au\u00dferdem verfolgen wir die \u00c4nderungen am Datenbankzustand, indem wir das Write-Ahead-Log (<noindex><a rel=\"nofollow\" href=\"https:\/\/www.postgresql.org\/docs\/current\/wal-intro.html\">write-ahead log<\/a><\/noindex>, WAL) archivieren. Mit all dem k\u00f6nnen wir PITR f\u00fcr die Notfallwiederherstellung durchf\u00fchren: Wir beginnen mit einem Snapshot, der vor dem Fehler gemacht wurde, und wenden die \u00c4nderungen aus dem WAL-Archiv bis zum Ausfall an.<\/p>\n<p><\/p>\n<h3 id=\"chto-takoe-otlozhennaya-replikaciya\">Was ist verz\u00f6gerte Replikation?<\/h3>\n<p><\/p>\n<p>Verz\u00f6gerte Replikation ist das Anwenden von \u00c4nderungen aus dem WAL mit Verz\u00f6gerung. Das hei\u00dft, die Transaktion fand um Uhr <code>X<\/code>statt, wird aber in der Replik mit Verz\u00f6gerung angezeigt <code>d<\/code> um Stunde <code>X + d<\/code>.<\/p>\n<p><\/p>\n<p>In PostgreSQL gibt es zwei M\u00f6glichkeiten, eine physische Datenbankreplikation einzurichten: die Wiederherstellung aus dem Archiv und die Streaming-Replikation. <noindex><a rel=\"nofollow\" href=\"https:\/\/www.postgresql.org\/docs\/current\/archive-recovery-settings.html\">Wiederherstellung aus dem Archiv<\/a><\/noindex>, funktioniert im Grunde wie PITR, jedoch kontinuierlich: Wir extrahieren st\u00e4ndig die \u00c4nderungen aus dem WAL-Archiv und wenden diese auf die Replik an. Die <noindex><a rel=\"nofollow\" href=\"https:\/\/wiki.postgresql.org\/wiki\/Streaming_Replication\">Streaming-Replikation<\/a><\/noindex> extrahiert direkt den WAL-Stream vom \u00fcbergeordneten Datenbankhost. Wir bevorzugen die Wiederherstellung aus dem Archiv \u2013 sie ist einfacher zu verwalten und bietet eine normale Leistung, die der des aktiven Clusters nicht nachsteht.<\/p>\n<p><\/p>\n<h3 id=\"kak-nastroit-otlozhennoe-vosstanovlenie-iz-arhiva\">So richten Sie die verz\u00f6gerte Wiederherstellung aus dem Archiv ein<\/h3>\n<p><\/p>\n<p><noindex><a rel=\"nofollow\" href=\"https:\/\/www.postgresql.org\/docs\/current\/recovery-config.html\">Wiederherstellungsoptionen<\/a><\/noindex> sind in der Datei <code>recovery.conf<\/code>. Beispiel:<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">standby_mode = 'on'\nrestore_command = '\/usr\/bin\/envdir \/etc\/wal-e.d\/env \/opt\/wal-e\/bin\/wal-e wal-fetch -p 4 \"%f\" \"%p\"'\nrecovery_min_apply_delay = '8h'\nrecovery_target_timeline = 'latest'<\/code><\/pre>\n<p><\/p>\n<p>Mit diesen Parametern haben wir eine verz\u00f6gerte Replikation mit Wiederherstellung aus dem Archiv eingerichtet. Hierbei verwenden wir <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/wal-e\/wal-e\">wal-e<\/a><\/noindex> zum Extrahieren der WAL-Segmente (<code>restore_command<\/code>) aus dem Archiv, und die \u00c4nderungen werden nach acht Stunden angewendet (<code>recovery_min_apply_delay<\/code>). Die Replik wird die \u00c4nderungen in der Zeitleiste im Archiv verfolgen, zum Beispiel aufgrund eines Ausfalls im Cluster (<code>recovery_target_timeline<\/code>).<\/p>\n<p><\/p>\n<p>E <code>recovery_min_apply_delay<\/code> Es ist m\u00f6glich, eine Streaming-Replikation mit Verz\u00f6gerung einzurichten, jedoch gibt es hier ein paar Fallstricke, die mit den Replikationsslots, dem Hot-Standby-Feedback und \u00e4hnlichem zu tun haben. Das WAL-Archiv hilft, diese zu umgehen.<\/p>\n<p><\/p>\n<p>Parameter <code>recovery_min_apply_delay<\/code> dies wurde erst in PostgreSQL 9.3 eingef\u00fchrt. In fr\u00fcheren Versionen musste eine Kombination f\u00fcr die verz\u00f6gerte Replikation eingerichtet werden. <noindex><a rel=\"nofollow\" href=\"https:\/\/www.postgresql.org\/docs\/9.3\/functions-admin.html\">Wiederherstellungsmanagement-Funktionen<\/a><\/noindex> (<code>pg_xlog_replay_pause(), pg_xlog_replay_resume()<\/code>) oder die WAL-Segmente w\u00e4hrend der Verz\u00f6gerungszeit im Archiv halten.<\/p>\n<p><\/p>\n<h3 id=\"kak-postgresql-eto-delaet\">Wie macht PostgreSQL das?<\/h3>\n<p><\/p>\n<p>Es ist interessant zu sehen, wie PostgreSQL die verz\u00f6gerte Wiederherstellung umsetzt. Schauen wir uns an, <noindex><a rel=\"nofollow\" href=\"https:\/\/gitlab.com\/postgres\/postgres\/blob\/c24dcd0cfd949bdf245814c4c2b3df828ee7db36\/src\/backend\/access\/transam\/xlog.c#L6124\"><code>recoveryApplyDelay(XlogReaderState)<\/code><\/a><\/noindex>. Dies wird aus dem <noindex><a rel=\"nofollow\" href=\"https:\/\/gitlab.com\/postgres\/postgres\/blob\/c24dcd0cfd949bdf245814c4c2b3df828ee7db36\/src\/backend\/access\/transam\/xlog.c#L7196\">Hauptwiederholungsschleife<\/a><\/noindex> f\u00fcr jeden Eintrag im WAL aufgerufen.<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">static bool\nrecoveryApplyDelay(XLogReaderState *record)\n{\n    uint8       xact_info;\n    TimestampTz xtime;\n    long        secs;\n    int         microsecs;\n\n    \/* nichts zu tun, wenn keine Verz\u00f6gerung konfiguriert ist *\/\n    if (recovery_min_apply_delay &lt;= 0)\n        return false;\n\n    \/* Keine Verz\u00f6gerung bei einer Datenbank, die noch nicht konsistent ist *\/\n    if (!reachedConsistency)\n        return false;\n\n    \/*\n     * Ist es ein COMMIT-Datensatz?\n     *\n     * Wir w\u00e4hlen absichtlich, keine Verz\u00f6gerung f\u00fcr Abbr\u00fcche anzuwenden, da sie keine\n     * Auswirkungen auf MVCC haben. Wir erlauben bereits die Wiedergabe von Datens\u00e4tzen,\n     * die keinen Zeitstempel haben,\n     * daher gibt es bereits Gelegenheiten f\u00fcr Probleme, die durch fr\u00fche Konflikte\n     * auf Standby-Systemen verursacht werden.\n     *\/\n    if (XLogRecGetRmid(record) != RM_XACT_ID)\n        return false;\n\n    xact_info = XLogRecGetInfo(record) &amp; XLOG_XACT_OPMASK;\n\n    if (xact_info != XLOG_XACT_COMMIT &amp;&amp;\n        xact_info != XLOG_XACT_COMMIT_PREPARED)\n        return false;\n\n    if (!getRecordTimestamp(record, &amp;xtime))\n        return false;\n\n    recoveryDelayUntilTime =\n        TimestampTzPlusMilliseconds(xtime, recovery_min_apply_delay);\n\n    \/*\n     * Beenden, ohne den Latch zu aktivieren, falls es bereits an der Zeit\n     * ist, diesen Datensatz anzuwenden\n     *\/\n    TimestampDifference(GetCurrentTimestamp(), recoveryDelayUntilTime,\n                        &amp;secs, &amp;microsecs);\n    if (secs &lt;= 0 &amp;&amp; microsecs &lt;= 0)\n        return false;\n\n    while (true)\n    {\n        \/\/ Abgek\u00fcrzt:\n        \/\/ Verwenden Sie WaitLatch, bis wir die recoveryDelayUntilTime erreicht haben\n        \/\/ und dann\n        break;\n    }\n    return true;\n}<\/code><\/pre>\n<p><\/p>\n<p>Der Kernpunkt ist, dass die Verz\u00f6gerung auf der physikalischen Zeit basiert, die in dem Zeitstempel der Transaktionsbest\u00e4tigung aufgezeichnet ist (<code>xtime<\/code>). Wie zu sehen ist, wird die Verz\u00f6gerung nur auf die Commits angewendet und betrifft keine anderen Eintr\u00e4ge \u2013 alle \u00c4nderungen werden direkt angewendet, w\u00e4hrend der Commit verz\u00f6gert wird, sodass wir die \u00c4nderungen erst nach der festgelegten Verz\u00f6gerung sehen.<\/p>\n<p><\/p>\n<h3 id=\"kak-ispolzovat-otlozhennuyu-repliku-dlya-vosstanovleniya-dannyh\">Wie man eine verz\u00f6gerte Replikat zur Datenwiederherstellung verwendet<\/h3>\n<p><\/p>\n<p>Angenommen, wir haben in der Produktion einen Datenbankcluster und eine Replikat mit einer achtst\u00fcndigen Verz\u00f6gerung. Schauen wir uns an, wie wir Daten anhand des Beispiels <noindex><a rel=\"nofollow\" href=\"https:\/\/gitlab.com\/gitlab-com\/gl-infra\/production\/issues\/509\">einer zuf\u00e4lligen L\u00f6schung von Verkn\u00fcpfungen<\/a><\/noindex>.<\/p>\n<p><\/p>\n<p>als wir von dem Problem erfuhren, haben wir <noindex><a rel=\"nofollow\" href=\"https:\/\/www.postgresql.org\/docs\/9.3\/functions-admin.html\">die Wiederherstellung aus dem Archiv angehalten<\/a><\/noindex> f\u00fcr die verz\u00f6gerte Replikat:<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">SELECT pg_xlog_replay_pause();<\/code><\/pre>\n<p><\/p>\n<p>Mit der Pause hatten wir kein Risiko, dass die Replikat die Anfrage wiederholt <code>DELETE<\/code>. N\u00fctzlich, wenn man Zeit ben\u00f6tigt, um alles zu kl\u00e4ren.<\/p>\n<p><\/p>\n<p>Die Idee ist, dass die verz\u00f6gerte Replikat bis zum Moment vor der Anfrage gelangen sollte <code>DELETE<\/code>. Wir wussten ungef\u00e4hr, wann die L\u00f6schung stattgefunden hat. Wir haben gel\u00f6scht <code>recovery_min_apply_delay<\/code> und hinzugef\u00fcgt <code>recovery_target_time<\/code> in <code>recovery.conf<\/code>. So erreicht die Replikat den gew\u00fcnschten Zeitpunkt ohne Verz\u00f6gerungen:<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">recovery_target_time = '2018-10-12 09:25:00+00'<\/code><\/pre>\n<p><\/p>\n<p>Bei Zeitstempeln sollte man lieber nicht zu viel abziehen, um nichts zu verpassen. Allerdings bedeutet eine gr\u00f6\u00dfere Abziehmenge, dass mehr Daten verloren gehen. Wiederum, wenn wir die Anfrage \u00fcberspringen. <code>DELETE<\/code>, alles wird wieder gel\u00f6scht und Sie m\u00fcssen von vorne beginnen (oder ein kaltes Backup f\u00fcr PITR \u00fcbernehmen).<\/p>\n<p><\/p>\n<p>Wir haben die verz\u00f6gerte Postgres-Instanz neu gestartet, und die WAL-Segmente wiederholten sich bis zu dem angegebenen Zeitpunkt. Den Fortschritt in dieser Phase k\u00f6nnen Sie mit der Abfrage verfolgen:<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">SELECT\n  -- aktuelle Position in WAL\n  pg_last_xlog_replay_location(),\n  -- aktueller Transaktionszeitstempel (Status des Replikats)\n  pg_last_xact_replay_timestamp(),\n  -- aktuelle physische Zeit\n  now(),\n  -- die Menge an Zeit, die noch angewendet werden muss, bis die recovery_target_time erreicht ist\n  '2018-10-12 09:25:00+00'::timestamptz - pg_last_xact_replay_timestamp() as delay;<\/code><\/pre>\n<p><\/p>\n<p>Wenn der Zeitstempel nicht mehr ver\u00e4ndert wird, ist die Wiederherstellung abgeschlossen. Sie k\u00f6nnen die Aktion <noindex><a rel=\"nofollow\" href=\"https:\/\/www.postgresql.org\/docs\/current\/recovery-target-settings.html\"><code>recovery_target_action<\/code><\/a><\/noindex>, um die Instanz nach der Wiederholung zu schlie\u00dfen, voranzutreiben oder anzuhalten (standardm\u00e4\u00dfig wird sie angehalten).<\/p>\n<p><\/p>\n<p>Die Datenbank ist in den Zustand vor der fehlerhaften Anfrage zur\u00fcckgekehrt. Jetzt k\u00f6nnen Sie beispielsweise Daten exportieren. Wir haben die gel\u00f6schten Daten zu den Labels und alle Verbindungen zu Aufgaben und Merge-Requests exportiert und in die Produktionsdatenbank \u00fcbertragen. Wenn die Verluste erheblich sind, k\u00f6nnen Sie einfach das Replikat voranbringen und als Hauptdatenbank verwenden. Aber dann gehen alle \u00c4nderungen nach dem Zeitpunkt verloren, zu dem wir wiederhergestellt haben.<\/p>\n<p><\/p>\n<p>Statt Zeitstempel sollten Transaktions-IDs verwendet werden. Es ist n\u00fctzlich, diese IDs aufzuzeichnen, zum Beispiel f\u00fcr DDL-Operatoren (wie <code>DROP TABLE<\/code>), mithilfe von <code>log_statements = 'ddl'<\/code>. H\u00e4tten wir die Transaktions-ID, w\u00fcrden wir <code>recovery_target_xid<\/code> nehmen und alles bis zur Transaktion vor der Anfrage ausf\u00fchren. <code>DELETE<\/code>.<\/p>\n<p><\/p>\n<p>Es ist sehr einfach, zur Arbeit zur\u00fcckzukehren: Entfernen Sie alle \u00c4nderungen aus <code>recovery.conf<\/code> und starten Sie Postgres neu. Bald wird die Replikation wieder eine achtst\u00fcndige Verz\u00f6gerung aufweisen, und wir sind bereit f\u00fcr zuk\u00fcnftige Probleme.<\/p>\n<p><\/p>\n<h3 id=\"preimuschestva-dlya-vosstanovleniya\">Vorteile der Wiederherstellung<\/h3>\n<p><\/p>\n<p>Mit einer verz\u00f6gerten Replikation m\u00fcssen wir nicht stundenlang ein vollst\u00e4ndiges Snapshot aus dem Archiv wiederherstellen. Es dauert bei uns beispielsweise f\u00fcnf Stunden, um das gesamte Basis-Backup von 2 TB abzurufen. Und dann m\u00fcssen wir auch noch das gesamte t\u00e4gliche WAL anwenden, um den gew\u00fcnschten Zustand wiederherzustellen (im schlimmsten Fall).<\/p>\n<p><\/p>\n<p>Eine verz\u00f6gerte Replikation ist in zwei Punkten besser als ein kaltes Backup:<\/p>\n<p><\/p>\n<ol>\n<li>Das gesamte Basis-Backup muss nicht aus dem Archiv entnommen werden.<\/li>\n<li>Es gibt ein festgelegtes achtst\u00fcndiges Fenster f\u00fcr die WAL-Segmente, die wiederholt werden m\u00fcssen.<\/li>\n<\/ol>\n<p><\/p>\n<p>Au\u00dferdem \u00fcberpr\u00fcfen wir st\u00e4ndig, ob ein PITR aus dem WAL m\u00f6glich ist, und w\u00fcrden schnell Sch\u00e4den oder andere Probleme mit dem WAL-Archiv bemerken, w\u00e4hrend wir die Verz\u00f6gerung der verz\u00f6gerten Replikation im Auge behalten.<\/p>\n<p><\/p>\n<p>In diesem Beispiel ben\u00f6tigten wir 50 Minuten f\u00fcr die Wiederherstellung, was einer Geschwindigkeit von 110 GB WAL-Daten pro Stunde entspricht (Archiv war zu diesem Zeitpunkt noch auf <noindex><a rel=\"nofollow\" href=\"https:\/\/aws.amazon.com\/s3\/\">AWS S3<\/a><\/noindex>). Insgesamt haben wir das Problem gel\u00f6st und die Daten in 1,5 Stunden wiederhergestellt.<\/p>\n<p><\/p>\n<h3 id=\"itogi-gde-prigoditsya-otlozhennaya-replika-a-gde-net\">Zusammenfassung: Wo ist verz\u00f6gerte Replikation sinnvoll (und wo nicht)<\/h3>\n<p><\/p>\n<p>Nutzen Sie verz\u00f6gerte Replikation als Erste-Hilfe-Ma\u00dfnahme, wenn Sie versehentlich Daten verloren haben und dieses Problem innerhalb der konfigurierten Verz\u00f6gerung bemerken.<\/p>\n<p><\/p>\n<blockquote><p>Aber beachten Sie: Replikation ist kein Backup.<\/p><\/blockquote>\n<p>Backup und Replikation haben unterschiedliche Ziele. Ein Kalt-Backup ist n\u00fctzlich, wenn Sie versehentlich gemacht haben <code>DELETE<\/code> oder <code>DROP TABLE<\/code>. Wir f\u00fchren ein Backup aus einem kalten Speicher durch und stellen den vorherigen Zustand einer Tabelle oder der gesamten Datenbank wieder her. Aber gleichzeitig wird die Anfrage <code>DROP TABLE<\/code> fast sofort in allen Replikaten des Arbeitsclusters reproduziert, sodass die gew\u00f6hnliche Replikation hier nicht hilft. An sich sorgt Replikation daf\u00fcr, dass die Datenbank verf\u00fcgbar bleibt, wenn einzelne Server ausfallen, und verteilt die Last.<\/p>\n<p><\/p>\n<p>Selbst mit einer verz\u00f6gerten Replikation ben\u00f6tigen wir manchmal dringend ein Kalt-Backup an einem sicheren Ort, falls es zu einem Ausfall des Rechenzentrums, einem verdeckten Schaden oder anderen Ereignissen kommt, die man nicht sofort bemerkt. Hier n\u00fctzt eine reine Replikation nichts.<\/p>\n<p><\/p>\n<p><strong>Hinweis<\/strong>. In <noindex><a rel=\"nofollow\" href=\"https:\/\/gitlab.com\/\">GitLab.com<\/a><\/noindex> Wir sch\u00fctzen derzeit Datenverlust nur auf Systemebene und stellen die Daten nicht auf Benutzerebene wieder her.<\/p>\n<p>Quelle: <a content=\"nofollow\" rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/southbridge\/blog\/445446\/\">habr.com<\/a><\/p>","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"excerpt":{"rendered":"<p>\u0420\u0435\u043f\u043b\u0438\u043a\u0430\u0446\u0438\u044f \u2014 \u043d\u0435 \u0431\u044d\u043a\u0430\u043f. \u0418\u043b\u0438 \u043d\u0435\u0442? \u0412\u043e\u0442 \u043a\u0430\u043a \u043c\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043b\u0438 \u043e\u0442\u043b\u043e\u0436\u0435\u043d\u043d\u0443\u044e \u0440\u0435\u043f\u043b\u0438\u043a\u0430\u0446\u0438\u044e \u0434\u043b\u044f \u0432\u043e\u0441\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f, \u0441\u043b\u0443\u0447\u0430\u0439\u043d\u043e \u0443\u0434\u0430\u043b\u0438\u0432 \u044f\u0440\u043b\u044b\u043a\u0438. \u0421\u043f\u0435\u0446\u0438\u0430\u043b\u0438\u0441\u0442\u044b \u043f\u043e \u0438\u043d\u0444\u0440\u0430\u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0435 \u043d\u0430 GitLab \u043e\u0442\u0432\u0435\u0447\u0430\u044e\u0442 \u0437\u0430 \u0440\u0430\u0431\u043e\u0442\u0443 GitLab.com \u2014 \u0441\u0430\u043c\u043e\u0433\u043e \u0431\u043e\u043b\u044c\u0448\u043e\u0433\u043e \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440\u0430 GitLab \u0432 \u043f\u0440\u0438\u0440\u043e\u0434\u0435. \u0417\u0434\u0435\u0441\u044c 3 \u043c\u0438\u043b\u043b\u0438\u043e\u043d\u0430 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439 \u0438 \u043f\u043e\u0447\u0442\u0438 7 \u043c\u0438\u043b\u043b\u0438\u043e\u043d\u043e\u0432 \u043f\u0440\u043e\u0435\u043a\u0442\u043e\u0432, \u0438 \u044d\u0442\u043e \u043e\u0434\u0438\u043d \u0438\u0437 \u0441\u0430\u043c\u044b\u0445 \u043a\u0440\u0443\u043f\u043d\u044b\u0445 \u043e\u043f\u0435\u043d\u0441\u043e\u0440\u0441-\u0441\u0430\u0439\u0442\u043e\u0432 SaaS \u0441 \u0432\u044b\u0434\u0435\u043b\u0435\u043d\u043d\u043e\u0439 \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u043e\u0439. \u0411\u0435\u0437 \u0441\u0438\u0441\u0442\u0435\u043c\u044b [&hellip;]<\/p>\n","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"author":1,"featured_media":22360,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[688],"tags":[],"class_list":["post-30356","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-administrirovanie"],"aioseo_notices":[],"aioseo_head":"\n\t\t<!-- All in One SEO 4.9.10 - aioseo.com -->\n\t<meta name=\"description\" content=\"\u0420\u0435\u043f\u043b\u0438\u043a\u0430\u0446\u0438\u044f \u2014 \u043d\u0435 \u0431\u044d\u043a\u0430\u043f. \u0418\u043b\u0438 \u043d\u0435\u0442? \u0412\u043e\u0442 \u043a\u0430\u043a \u043c\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043b\u0438 \u043e\u0442\u043b\u043e\u0436\u0435\u043d\u043d\u0443\u044e \u0440\u0435\u043f\u043b\u0438\u043a\u0430\u0446\u0438\u044e \u0434\u043b\u044f \u0432\u043e\u0441\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f, \u0441\u043b\u0443\u0447\u0430\u0439\u043d\u043e \u0443\u0434\u0430\u043b\u0438\u0432 \u044f\u0440\u043b\u044b\u043a\u0438. \u0421\u043f\u0435\u0446\u0438\u0430\u043b\u0438\u0441\u0442\u044b \u043f\u043e \u0438\u043d\u0444\u0440\u0430\u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0435 \u043d\u0430 GitLab \u043e\u0442\u0432\u0435\u0447\u0430\u044e\u0442 \u0437\u0430 \u0440\u0430\u0431\u043e\u0442\u0443 GitLab.com \u2014 \u0441\u0430\u043c\u043e\u0433\u043e \u0431\u043e\u043b\u044c\u0448\u043e\u0433\u043e \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440\u0430 GitLab \u0432 \u043f\u0440\u0438\u0440\u043e\u0434\u0435. \u0417\u0434\u0435\u0441\u044c 3 \u043c\u0438\u043b\u043b\u0438\u043e\u043d\u0430 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439 \u0438 \u043f\u043e\u0447\u0442\u0438 7 \u043c\u0438\u043b\u043b\u0438\u043e\u043d\u043e\u0432 \u043f\u0440\u043e\u0435\u043a\u0442\u043e\u0432, \u0438 \u044d\u0442\u043e \u043e\u0434\u0438\u043d \u0438\u0437 \u0441\u0430\u043c\u044b\u0445 \u043a\u0440\u0443\u043f\u043d\u044b\u0445 \u043e\u043f\u0435\u043d\u0441\u043e\u0440\u0441-\u0441\u0430\u0439\u0442\u043e\u0432 SaaS \u0441 \u0432\u044b\u0434\u0435\u043b\u0435\u043d\u043d\u043e\u0439 \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u043e\u0439. \u0411\u0435\u0437 \u0441\u0438\u0441\u0442\u0435\u043c\u044b\" \/>\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\/kak-my-ispolzovali-otlozhennuyu-replikatsiyu-dlya-avarijnogo-vosstanovleniya-s-postgresql\" \/>\n\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 4.9.10\" \/>\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\u041a\u0430\u043a \u043c\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043b\u0438 \u043e\u0442\u043b\u043e\u0436\u0435\u043d\u043d\u0443\u044e \u0440\u0435\u043f\u043b\u0438\u043a\u0430\u0446\u0438\u044e \u0434\u043b\u044f \u0430\u0432\u0430\u0440\u0438\u0439\u043d\u043e\u0433\u043e \u0432\u043e\u0441\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f \u0441 PostgreSQL | ProHoster\" \/>\n\t\t<meta property=\"og:description\" content=\"\u0420\u0435\u043f\u043b\u0438\u043a\u0430\u0446\u0438\u044f \u2014 \u043d\u0435 \u0431\u044d\u043a\u0430\u043f. \u0418\u043b\u0438 \u043d\u0435\u0442? \u0412\u043e\u0442 \u043a\u0430\u043a \u043c\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043b\u0438 \u043e\u0442\u043b\u043e\u0436\u0435\u043d\u043d\u0443\u044e \u0440\u0435\u043f\u043b\u0438\u043a\u0430\u0446\u0438\u044e \u0434\u043b\u044f \u0432\u043e\u0441\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f, \u0441\u043b\u0443\u0447\u0430\u0439\u043d\u043e \u0443\u0434\u0430\u043b\u0438\u0432 \u044f\u0440\u043b\u044b\u043a\u0438. \u0421\u043f\u0435\u0446\u0438\u0430\u043b\u0438\u0441\u0442\u044b \u043f\u043e \u0438\u043d\u0444\u0440\u0430\u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0435 \u043d\u0430 GitLab \u043e\u0442\u0432\u0435\u0447\u0430\u044e\u0442 \u0437\u0430 \u0440\u0430\u0431\u043e\u0442\u0443 GitLab.com \u2014 \u0441\u0430\u043c\u043e\u0433\u043e \u0431\u043e\u043b\u044c\u0448\u043e\u0433\u043e \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440\u0430 GitLab \u0432 \u043f\u0440\u0438\u0440\u043e\u0434\u0435. \u0417\u0434\u0435\u0441\u044c 3 \u043c\u0438\u043b\u043b\u0438\u043e\u043d\u0430 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439 \u0438 \u043f\u043e\u0447\u0442\u0438 7 \u043c\u0438\u043b\u043b\u0438\u043e\u043d\u043e\u0432 \u043f\u0440\u043e\u0435\u043a\u0442\u043e\u0432, \u0438 \u044d\u0442\u043e \u043e\u0434\u0438\u043d \u0438\u0437 \u0441\u0430\u043c\u044b\u0445 \u043a\u0440\u0443\u043f\u043d\u044b\u0445 \u043e\u043f\u0435\u043d\u0441\u043e\u0440\u0441-\u0441\u0430\u0439\u0442\u043e\u0432 SaaS \u0441 \u0432\u044b\u0434\u0435\u043b\u0435\u043d\u043d\u043e\u0439 \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u043e\u0439. \u0411\u0435\u0437 \u0441\u0438\u0441\u0442\u0435\u043c\u044b\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/prohoster.info\/de\/blog\/administrirovanie\/kak-my-ispolzovali-otlozhennuyu-replikatsiyu-dlya-avarijnogo-vosstanovleniya-s-postgresql\" \/>\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=\"2019-10-31T18:35:06+00:00\" \/>\n\t\t<meta property=\"article:modified_time\" content=\"2019-10-31T18:35:06+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\udd47 So haben wir verz\u00f6gerte Replikation f\u00fcr die Notfallwiederherstellung mit PostgreSQL genutzt | ProHoster","description":"Replikation ist kein Backup. Oder doch? So haben wir verz\u00f6gerte Replikation genutzt, um versehentlich gel\u00f6schte Verkn\u00fcpfungen wiederherzustellen. Die Infrastruktur-Experten bei GitLab sind f\u00fcr den Betrieb von GitLab.com verantwortlich \u2014 dem gr\u00f6\u00dften GitLab-Exemplar weltweit. Hier gibt es 3 Millionen Nutzer und fast 7 Millionen Projekte, was es zu einer der gr\u00f6\u00dften Open-Source-SaaS-Plattformen mit einer dedizierten Architektur macht. Ohne System.","canonical_url":"https:\/\/prohoster.info\/de\/blog\/administrirovanie\/kak-my-ispolzovali-otlozhennuyu-replikatsiyu-dlya-avarijnogo-vosstanovleniya-s-postgresql","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\u041a\u0430\u043a \u043c\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043b\u0438 \u043e\u0442\u043b\u043e\u0436\u0435\u043d\u043d\u0443\u044e \u0440\u0435\u043f\u043b\u0438\u043a\u0430\u0446\u0438\u044e \u0434\u043b\u044f \u0430\u0432\u0430\u0440\u0438\u0439\u043d\u043e\u0433\u043e \u0432\u043e\u0441\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f \u0441 PostgreSQL | ProHoster","og:description":"\u0420\u0435\u043f\u043b\u0438\u043a\u0430\u0446\u0438\u044f \u2014 \u043d\u0435 \u0431\u044d\u043a\u0430\u043f. \u0418\u043b\u0438 \u043d\u0435\u0442? \u0412\u043e\u0442 \u043a\u0430\u043a \u043c\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043b\u0438 \u043e\u0442\u043b\u043e\u0436\u0435\u043d\u043d\u0443\u044e \u0440\u0435\u043f\u043b\u0438\u043a\u0430\u0446\u0438\u044e \u0434\u043b\u044f \u0432\u043e\u0441\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f, \u0441\u043b\u0443\u0447\u0430\u0439\u043d\u043e \u0443\u0434\u0430\u043b\u0438\u0432 \u044f\u0440\u043b\u044b\u043a\u0438. \u0421\u043f\u0435\u0446\u0438\u0430\u043b\u0438\u0441\u0442\u044b \u043f\u043e \u0438\u043d\u0444\u0440\u0430\u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0435 \u043d\u0430 GitLab \u043e\u0442\u0432\u0435\u0447\u0430\u044e\u0442 \u0437\u0430 \u0440\u0430\u0431\u043e\u0442\u0443 GitLab.com \u2014 \u0441\u0430\u043c\u043e\u0433\u043e \u0431\u043e\u043b\u044c\u0448\u043e\u0433\u043e \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440\u0430 GitLab \u0432 \u043f\u0440\u0438\u0440\u043e\u0434\u0435. \u0417\u0434\u0435\u0441\u044c 3 \u043c\u0438\u043b\u043b\u0438\u043e\u043d\u0430 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439 \u0438 \u043f\u043e\u0447\u0442\u0438 7 \u043c\u0438\u043b\u043b\u0438\u043e\u043d\u043e\u0432 \u043f\u0440\u043e\u0435\u043a\u0442\u043e\u0432, \u0438 \u044d\u0442\u043e \u043e\u0434\u0438\u043d \u0438\u0437 \u0441\u0430\u043c\u044b\u0445 \u043a\u0440\u0443\u043f\u043d\u044b\u0445 \u043e\u043f\u0435\u043d\u0441\u043e\u0440\u0441-\u0441\u0430\u0439\u0442\u043e\u0432 SaaS \u0441 \u0432\u044b\u0434\u0435\u043b\u0435\u043d\u043d\u043e\u0439 \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u043e\u0439. \u0411\u0435\u0437 \u0441\u0438\u0441\u0442\u0435\u043c\u044b","og:url":"https:\/\/prohoster.info\/de\/blog\/administrirovanie\/kak-my-ispolzovali-otlozhennuyu-replikatsiyu-dlya-avarijnogo-vosstanovleniya-s-postgresql","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":"2019-10-31T18:35:06+00:00","article:modified_time":"2019-10-31T18:35:06+00:00","article:publisher":"https:\/\/www.facebook.com\/prohoster","article:author":"https:\/\/www.facebook.com\/prohoster"},"aioseo_meta_data":{"post_id":"30356","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":"2026-01-21 00:50:19","breadcrumb_settings":null,"limit_modified_date":false,"reviewed_by":null,"ai":null,"created":"2021-02-28 11:48:29","updated":"2026-01-21 00:50:19"},"gt_translate_keys":[{"key":"link","format":"url"}],"_links":{"self":[{"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/posts\/30356","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=30356"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/posts\/30356\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/media\/22360"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/media?parent=30356"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/categories?post=30356"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/tags?post=30356"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}