{"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 genutzt 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 genutzt haben\" src=\"\/wp-content\/uploads\/2019\/03\/773f3b6c8d173be91c49066d7067bad3.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nReplikation ist kein Backup. Oder etwa doch? So haben wir verz\u00f6gerte Replikation f\u00fcr die Wiederherstellung genutzt, nachdem wir versehentlich Labels gel\u00f6scht haben.<\/p>\n<p><\/p>\n<p><noindex><a rel=\"nofollow\" href=\"https:\/\/about.gitlab.com\/handbook\/engineering\/infrastructure\/\">Infrastruktur-Experten<\/a><\/noindex> bei GitLab sind verantwortlich f\u00fcr den Betrieb <noindex><a rel=\"nofollow\" href=\"https:\/\/gitlab.com\/\">GitLab.com<\/a><\/noindex> \u2014 der gr\u00f6\u00dften GitLab-Instanz der Welt. Hier gibt es 3 Millionen Benutzer und fast 7 Millionen Projekte, und es ist eine der gr\u00f6\u00dften Open-Source-SaaS-Seiten mit einer dedizierten Architektur. Ohne das Datenbanksystem PostgreSQL w\u00fcrde GitLab.com nicht weit kommen, und was wir nicht alles tun, um die Ausfallsicherheit f\u00fcr den Fall von Fehlern, die zu Datenverlust f\u00fchren k\u00f6nnen, zu gew\u00e4hrleisten. So eine Katastrophe wird wahrscheinlich nicht eintreten, aber wir sind gut vorbereitet und haben verschiedene Backup- und Replikationsmechanismen vorr\u00e4tig.<\/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 mithilfe von verz\u00f6gerter Replikation schnell wiederherstellt: ich <noindex><a rel=\"nofollow\" href=\"https:\/\/gitlab.com\/\">GitLab.com<\/a><\/noindex> Nutzer <noindex><a rel=\"nofollow\" href=\"https:\/\/gitlab.com\/gitlab-com\/gl-infra\/production\/issues\/509\">habe ein Label<\/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 Verbindung zu Merge-Requests und Aufgaben verloren.<\/p>\n<p><\/p>\n<p>Mit der verz\u00f6gerten Replikation konnten wir die Daten in nur 1,5 Stunden wiederherstellen. Sehen Sie, wie es war.<\/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 eingebaute Funktion, die den Zustand der Datenbank zu einem bestimmten Zeitpunkt wiederherstellt. Sie wird genannt <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 Replikation unterst\u00fctzen: Ausgehend von einem verl\u00e4sslichen Snapshot des gesamten Datenbank-Clusters (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 kalte Backups zu nutzen, erstellen wir regelm\u00e4\u00dfig ein Basis-Backup der Datenbank und speichern es in einem Archiv (Archiven von GitLab leben in <noindex><a rel=\"nofollow\" href=\"https:\/\/cloud.google.com\/storage\/\">Google Cloud Storage<\/a><\/noindex>). Au\u00dferdem verfolgen wir die Zustands\u00e4nderungen der Datenbank, 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 dem Snapshot, der vor dem Fehler erstellt wurde, und wenden die \u00c4nderungen aus dem WAL-Archiv bis zum Fehler 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 bedeutet, dass \u00c4nderungen aus dem WAL mit einer Verz\u00f6gerung angewendet werden. Das hei\u00dft, die Transaktion fand um eine Uhr <code>X<\/code>statt, wird aber mit einer Verz\u00f6gerung <code>d<\/code> von einer Stunde <code>in der Replikation erscheinen.<\/code>.<\/p>\n<p><\/p>\n<p>In PostgreSQL gibt es zwei M\u00f6glichkeiten, eine physische Datenbankreplikation einzurichten: Wiederherstellung aus dem Archiv und 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 Wesentlichen wie PITR, aber kontinuierlich: Wir extrahieren st\u00e4ndig \u00c4nderungen aus dem WAL-Archiv und wenden sie auf die Replik an. W\u00e4hrend <noindex><a rel=\"nofollow\" href=\"https:\/\/wiki.postgresql.org\/wiki\/Streaming_Replication\">Streaming-Replikation<\/a><\/noindex> direkt einen WAL-Stream vom \u00fcbergeordneten Datenbankhost extrahiert. Wir ziehen die Wiederherstellung aus dem Archiv vor \u2013 sie ist einfacher zu verwalten und hat eine normale Leistung, die mit dem Arbeitscluster nicht hinterherhinkt.<\/p>\n<p><\/p>\n<h3 id=\"kak-nastroit-otlozhennoe-vosstanovlenie-iz-arhiva\">Wie man eine verz\u00f6gerte Wiederherstellung aus dem Archiv einrichtet<\/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. Dabei wird <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/wal-e\/wal-e\">wal-e<\/a><\/noindex> zur Extraktion von WAL-Segmenten (<code>restore_command<\/code>) aus dem Archiv verwendet, und \u00c4nderungen werden nach acht Stunden angewendet (<code>recovery_min_apply_delay<\/code>). Die Replik wird die \u00c4nderungen auf der Zeitachse im Archiv verfolgen, beispielsweise aufgrund von Fehlschl\u00e4gen im Cluster (<code>recovery_target_timeline<\/code>).<\/p>\n<p><\/p>\n<p>C <code>recovery_min_apply_delay<\/code> es ist m\u00f6glich, eine verz\u00f6gerte Streaming-Replikation einzurichten, aber es gibt ein paar Fallstricke, die mit Replikationsslots, Hot-Standby-Feedback usw. zusammenh\u00e4ngen. Das WAL-Archiv erm\u00f6glicht es, diese zu vermeiden.<\/p>\n<p><\/p>\n<p>Parameter <code>recovery_min_apply_delay<\/code> wurde erst in PostgreSQL 9.3 eingef\u00fchrt. In fr\u00fcheren Versionen musste man eine Kombination aus <noindex><a rel=\"nofollow\" href=\"https:\/\/www.postgresql.org\/docs\/9.3\/functions-admin.html\">Wiederherstellungsmanagementfunktionen<\/a><\/noindex> (<code>pg_xlog_replay_pause(), pg_xlog_replay_resume()<\/code>) einrichten oder 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 eine verz\u00f6gerte Wiederherstellung implementiert. Schauen wir uns <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>. Es wird im <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 aus dem 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 gilt f\u00fcr eine Datenbank, die noch nicht konsistent ist *\/\n    if (!reachedConsistency)\n        return false;\n\n    \/*\n     * Ist es ein COMMIT-Posten?\n     *\n     * Wir entscheiden uns bewusst, Abbr\u00fcche nicht zu verz\u00f6gern, da sie keine Auswirkungen auf\n     * MVCC haben. Wir erlauben bereits die Wiedergabe von Posten, die keinen Zeitstempel haben,\n     * daher gibt es bereits M\u00f6glichkeiten f\u00fcr Probleme, die durch fr\u00fche Konflikte auf\n     * 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     * Verlasse ohne das Latch zu aktivieren, wenn es bereits Zeit ist, diesen\n     * Posten 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        \/\/ Verk\u00fcrzt:\n        \/\/ Benutze WaitLatch, bis wir die recoveryDelayUntilTime erreicht haben\n        \/\/ und dann\n        break;\n    }\n    return true;\n}<\/code><\/pre>\n<p><\/p>\n<p>Das Wesentliche ist, dass die Verz\u00f6gerung auf der physischen Zeit basiert, die im Zeitstempel des Transaktions-Commits verzeichnet ist (<code>xtime<\/code>). Wie zu erkennen ist, wird die Verz\u00f6gerung nur auf Commits angewendet und betrifft keine anderen Posten \u2013 alle \u00c4nderungen werden direkt angewendet, w\u00e4hrend der Commit verz\u00f6gert wird, sodass wir \u00c4nderungen erst nach der eingestellten Verz\u00f6gerung sehen.<\/p>\n<p><\/p>\n<h3 id=\"kak-ispolzovat-otlozhennuyu-repliku-dlya-vosstanovleniya-dannyh\">Wie man eine verz\u00f6gerte Replikation zur Datenwiederherstellung nutzt<\/h3>\n<p><\/p>\n<p>Angenommen, wir haben in der Produktion einen Datenbankcluster und eine Replikation mit einer Verz\u00f6gerung von acht Stunden. Schauen wir uns an, wie wir Daten am Beispiel von <noindex><a rel=\"nofollow\" href=\"https:\/\/gitlab.com\/gitlab-com\/gl-infra\/production\/issues\/509\">willk\u00fcrlichem L\u00f6schen von Verkn\u00fcpfungen<\/a><\/noindex>.<\/p>\n<p><\/p>\n<p>wiederherstellen k\u00f6nnen, 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 Replikation:<\/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 Replikation die Anfrage wiederholt <code>DELETE<\/code>. N\u00fctzlich, wenn man Zeit braucht, um alles zu kl\u00e4ren.<\/p>\n<p><\/p>\n<p>Das Wesentliche ist, dass die verz\u00f6gerte Replikation bis zu dem Zeitpunkt vor der Anfrage kommen muss <code>DELETE<\/code>. Wir wussten ungef\u00e4hr die physische Zeit der L\u00f6schung. Wir haben gel\u00f6scht <code>recovery_min_apply_delay<\/code> und hinzugef\u00fcgt <code>recovery_target_time<\/code> in <code>recovery.conf<\/code>. So kommt die Replikation zum 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>Beim Zeitstempel sollte man nichts \u00fcbertreiben, um keine Fehler zu machen. Allerdings, je mehr man abzieht, desto mehr Daten verlieren wir. Wiederum, wenn wir die Anfrage \u00fcbersehen <code>DELETE<\/code>, wird alles erneut gel\u00f6scht und wir m\u00fcssen von vorne beginnen (oder sogar ein kaltes Backup f\u00fcr PITR nehmen).<\/p>\n<p><\/p>\n<p>Wir haben die verschobene Postgres-Instanz neu gestartet, und die WAL-Segmente wiederholten sich bis zur angegebenen Zeit. Den Fortschritt zu diesem Zeitpunkt kann man mit der Abfrage verfolgen:<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">SELECT\n  -- aktuelle Position im WAL\n  pg_last_xlog_replay_location(),\n  -- aktueller Transaktionszeitstempel (Zustand der Replik)\n  pg_last_xact_replay_timestamp(),\n  -- aktuelle physische Zeit\n  now(),\n  -- die Zeit, die noch bis zum Erreichen der recovery_target_time angewendet werden muss\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 wechselt, ist die Wiederherstellung abgeschlossen. Man kann die Aktion einstellen <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 (standardm\u00e4\u00dfig wird sie angehalten) zu schlie\u00dfen, voranzutreiben oder anzuhalten.<\/p>\n<p><\/p>\n<p>Die Datenbank hat den Zustand vor der problematischen Abfrage erreicht. Jetzt kann man zum Beispiel Daten exportieren. Wir haben die entfernten Daten \u00fcber das Label sowie alle Verbindungen zu Aufgaben und Merge-Requests exportiert und in die Arbeitsdatenbank \u00fcbertragen. Falls die Verluste erheblich sind, kann man einfach die Replik vorantreiben und sie als Hauptdatenbank verwenden. Aber dabei gehen alle \u00c4nderungen nach dem Zeitpunkt verloren, zu dem wir zur\u00fcckgekehrt sind.<\/p>\n<p><\/p>\n<p>Statt Zeitstempeln sollten besser 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 eine Transaktions-ID, k\u00f6nnten wir die <code>recovery_target_xid<\/code> nehmen und alles bis zur Transaktion vor der Abfrage durchlaufen. <code>DELETE<\/code>.<\/p>\n<p><\/p>\n<p>Zur\u00fcck an die Arbeit ist ganz einfach: Entfernen Sie alle \u00c4nderungen aus <code>recovery.conf<\/code> und starten Sie Postgres neu. Bald wird wieder eine achtst\u00fcndige Verz\u00f6gerung in der Replik auftreten, und wir sind bereit f\u00fcr zuk\u00fcnftige Probleme.<\/p>\n<p><\/p>\n<h3 id=\"preimuschestva-dlya-vosstanovleniya\">Vorteile f\u00fcr die Wiederherstellung<\/h3>\n<p><\/p>\n<p>Mit einer verz\u00f6gerten Replikation anstelle eines kalten Backups muss man nicht stundenlang ein ganzes Snapshot aus dem Archiv wiederherstellen. Wir ben\u00f6tigen zum Beispiel f\u00fcnf Stunden, um das gesamte Basisbackup von 2 TB zu extrahieren. Au\u00dferdem muss das gesamte t\u00e4gliche WAL angewendet werden, um den gew\u00fcnschten Zustand zu erreichen (im schlimmsten Fall).<\/p>\n<p><\/p>\n<p>Eine verz\u00f6gerte Replik ist in zwei Punkten besser als ein kaltes Backup:<\/p>\n<p><\/p>\n<ol>\n<li>Es ist nicht notwendig, das gesamte Basisbackup aus dem Archiv zu holen.<\/li>\n<li>Es gibt ein festes achtst\u00fcndiges Fenster von WAL-Segmenten, die wiederholt werden m\u00fcssen.<\/li>\n<\/ol>\n<p><\/p>\n<p>Au\u00dferdem \u00fcberpr\u00fcfen wir st\u00e4ndig, ob PITR aus dem WAL m\u00f6glich ist, und wir w\u00fcrden schnell Sch\u00e4den oder andere Probleme mit dem WAL-Archiv feststellen, w\u00e4hrend wir die Verz\u00f6gerung der verz\u00f6gerten Replik beobachten.<\/p>\n<p><\/p>\n<p>In diesem Beispiel dauerte die Wiederherstellung 50 Minuten, was einer Geschwindigkeit von 110 GB WAL-Daten pro Stunde entsprach (das Archiv war damals 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\">Ergebnisse: Wo sich eine verz\u00f6gerte Replikation bew\u00e4hrt (und wo nicht)<\/h3>\n<p><\/p>\n<p>Verwenden Sie verz\u00f6gerte Replikation als Notfallma\u00dfnahme, wenn Sie versehentlich Daten verloren haben und diesen Fehler innerhalb der festgelegten Verz\u00f6gerung bemerken.<\/p>\n<p><\/p>\n<blockquote><p>Aber denken Sie daran: Replikation ist kein Backup.<\/p><\/blockquote>\n<p>Backup und Replikation haben unterschiedliche Ziele. Ein kaltes Backup ist n\u00fctzlich, wenn Sie versehentlich <code>DELETE<\/code> oder <code>DROP TABLE<\/code>. Wir erstellen ein Backup aus einem kalten Speicher und stellen den vorherigen Zustand der Tabelle oder der gesamten Datenbank wieder her. Aber in diesem Fall wird die Anfrage <code>DROP TABLE<\/code> nahezu sofort in allen Replikaten des Arbeitsclusters reproduziert, daher hilft die normale Replikation hier nicht. Die Replikation selbst h\u00e4lt die Datenbank verf\u00fcgbar, 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 kaltes Backup an einem sicheren Ort, falls es zu einem Ausfall des Rechenzentrums, versteckten Besch\u00e4digungen oder anderen Ereignissen kommt, die sofort nicht bemerkt werden. Hier n\u00fctzt eine reine Replikation nichts.<\/p>\n<p><\/p>\n<p><strong>Hinweis<\/strong>. Auf der <noindex><a rel=\"nofollow\" href=\"https:\/\/gitlab.com\/\">GitLab.com<\/a><\/noindex> Wir sch\u00fctzen derzeit nur auf Systemebene vor Datenverlust 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 5.0.1.1 - aioseo.com -->\n\t<meta name=\"description\" content=\".\" \/>\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) 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\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=\".\" \/>\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\udd47Wie wir verz\u00f6gerte Replikation f\u00fcr eine Notfallwiederherstellung mit PostgreSQL verwendet haben | ProHoster","description":".","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":".","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","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\/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}]}}