{"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\/da\/blog\/administrirovanie\/kak-my-ispolzovali-otlozhennuyu-replikatsiyu-dlya-avarijnogo-vosstanovleniya-s-postgresql","title":{"rendered":"Hvordan vi brugte forsinket replication til disaster recovery med PostgreSQL","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p><img decoding=\"async\" alt=\"Hvordan vi brugte forsinket replication til disaster recovery med PostgreSQL\" src=\"\/wp-content\/uploads\/2019\/03\/773f3b6c8d173be91c49066d7067bad3.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nReplikering er ikke backup. Eller er det? Her er, hvordan vi brugte forsinket replikering til at gendanne data efter ved et uheld at have slettet genveje.<\/p>\n<p><\/p>\n<p><noindex><a rel=\"nofollow\" href=\"https:\/\/about.gitlab.com\/handbook\/engineering\/infrastructure\/\">Infrastructure specialists<\/a><\/noindex> on GitLab are responsible for the operation <noindex><a rel=\"nofollow\" href=\"https:\/\/gitlab.com\/\">GitLab.com<\/a><\/noindex> \u2014 of the largest instance of GitLab in existence. Here, there are 3 million users and almost 7 million projects, making it one of the largest open-source SaaS sites with dedicated architecture. Without the PostgreSQL database system, GitLab.com would struggle, and we do everything possible for redundancy in the event of failures when data might be lost. While such a disaster is unlikely, we are well-prepared and equipped with various backup and replication mechanisms.<\/p>\n<p><\/p>\n<p>Replikering er ikke et middel til databasebackup (<noindex><a rel=\"nofollow\" href=\"https:\/\/about.gitlab.com\/2019\/02\/13\/delayed-replication-for-disaster-recovery-with-postgresql\/#summing-up\">se nedenfor<\/a><\/noindex>). Men nu skal vi se, hvordan vi hurtigt kan gendanne ved et uheld slettede data ved hj\u00e6lp af forsinket replikering: ved <noindex><a rel=\"nofollow\" href=\"https:\/\/gitlab.com\/\">GitLab.com<\/a><\/noindex> bruger <noindex><a rel=\"nofollow\" href=\"https:\/\/gitlab.com\/gitlab-com\/gl-infra\/production\/issues\/509\">at have slettet en genvej<\/a><\/noindex> til projektet <noindex><a rel=\"nofollow\" href=\"https:\/\/gitlab.com\/gitlab-org\/gitlab-ce\/\"><code>gitlab-ce<\/code><\/a><\/noindex> og mistet forbindelsen til merge-requests og opgaver.<\/p>\n<p><\/p>\n<p>Med forsinket replikation gendannede vi data p\u00e5 kun 1,5 time. Se, hvordan det blev gjort.<\/p>\n<p><noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<h3 id=\"vosstanovlenie-na-moment-vremeni-s-postgresql\">Gendannelse til et bestemt tidspunkt med PostgreSQL<\/h3>\n<p><\/p>\n<p>PostgreSQL har en indbygget funktion, der gendanner databasens tilstand til et bestemt tidspunkt. Den kaldes <noindex><a rel=\"nofollow\" href=\"https:\/\/www.postgresql.org\/docs\/current\/continuous-archiving.html\">Point-in-Time Recovery<\/a><\/noindex> (PITR) og bruger de samme mekanismer, der holder replikationen ajour: vi starter med et p\u00e5lideligt snapshot af hele databaseklusteret (grundl\u00e6ggende backup) og anvender en r\u00e6kke tilstands\u00e6ndringer indtil et bestemt tidspunkt.<\/p>\n<p><\/p>\n<p>For at bruge denne funktion til en kold backup, laver vi regelm\u00e6ssigt en grundl\u00e6ggende databasebackup og gemmer den i arkivet (GitLab-arkiver findes i <noindex><a rel=\"nofollow\" href=\"https:\/\/cloud.google.com\/storage\/\">Google Cloud Storage<\/a><\/noindex>). Og vi overv\u00e5ger ogs\u00e5 databasens tilstands\u00e6ndringer ved at arkivere write-ahead-log (<noindex><a rel=\"nofollow\" href=\"https:\/\/www.postgresql.org\/docs\/current\/wal-intro.html\">write-ahead log<\/a><\/noindex>, WAL). Med alt dette kan vi udf\u00f8re PITR for n\u00f8dgendannelse: vi starter med et snapshot taget f\u00f8r fejlen og anvender \u00e6ndringerne fra WAL-arkivet frem til fejlen.<\/p>\n<p><\/p>\n<h3 id=\"chto-takoe-otlozhennaya-replikaciya\">Hvad er forsinket replikering?<\/h3>\n<p><\/p>\n<p>Forsinket replikering er anvendelse af \u00e6ndringer fra WAL med forsinkelse. Det vil sige, at transaktionen opstod i time <code>X<\/code>, men i replikationen vil den vises med en forsinkelse <code>d<\/code> p\u00e5 en time <code>X + d<\/code>.<\/p>\n<p><\/p>\n<p>I PostgreSQL er der to m\u00e5der at konfigurere en fysisk database-replikation: gendannelse fra arkiv og streaming-replikation. <noindex><a rel=\"nofollow\" href=\"https:\/\/www.postgresql.org\/docs\/current\/archive-recovery-settings.html\">Gendannelse fra arkiv<\/a><\/noindex>, i princippet fungerer det som PITR, men kontinuerligt: vi tr\u00e6kker konstant \u00e6ndringer fra WAL-arkivet og anvender dem p\u00e5 replikatet. A <noindex><a rel=\"nofollow\" href=\"https:\/\/wiki.postgresql.org\/wiki\/Streaming_Replication\">streaming-replikation<\/a><\/noindex> udtr\u00e6kker direkte WAL-str\u00f8mmen fra den overordnede databasehost. Vi foretr\u00e6kker genopretning fra arkivet \u2014 det er lettere at administrere, og det har en normal ydeevne, der ikke halter bagefter arbejdsclusteret.<\/p>\n<p><\/p>\n<h3 id=\"kak-nastroit-otlozhennoe-vosstanovlenie-iz-arhiva\">Hvordan man konfigurerer forsinket genopretning fra arkivet<\/h3>\n<p><\/p>\n<p><noindex><a rel=\"nofollow\" href=\"https:\/\/www.postgresql.org\/docs\/current\/recovery-config.html\">Genoprettelsesindstillinger<\/a><\/noindex> er beskrevet i filen <code>recovery.conf<\/code>. Eksempel:<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">standby_mode = 'on'\nrestore_command = '\u2044usr\u2044bin\u2044envdir \u2044etc\u2044wal-e.d\u2044env \u2044opt\u2044wal-e\u2044bin\u2044wal-e wal-fetch -p 4 \"%f\" \"%p\"'\nrecovery_min_apply_delay = '8h'\nrecovery_target_timeline = 'latest'<\/code><\/pre>\n<p><\/p>\n<p>Med disse indstillinger har vi konfigureret en forsinket replika med genopretning fra arkivet. Her bruges <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/wal-e\/wal-e\">wal-e<\/a><\/noindex> til at udtr\u00e6kke WAL-segmenter (<code>restore_command<\/code>) fra arkivet, og \u00e6ndringerne vil blive anvendt om otte timer (<code>recovery_min_apply_delay<\/code>). Replikatet vil overv\u00e5ge \u00e6ndringer i tidslinjen i arkivet, for eksempel p\u00e5 grund af fejlh\u00e5ndtering i clusteren (<code>recovery_target_timeline<\/code>).<\/p>\n<p><\/p>\n<p>Med <code>recovery_min_apply_delay<\/code> kan konfigureres til streaming-replikation med forsinkelse, men der er et par faldgruber forbundet med replikationsslots, feedback fra den varme reservemodus osv. WAL-arkivet g\u00f8r det muligt at undg\u00e5 dem.<\/p>\n<p><\/p>\n<p>Parameter <code>recovery_min_apply_delay<\/code> kom f\u00f8rst til PostgreSQL 9.3. I tidligere versioner skulle man konfigurere en kombination af <noindex><a rel=\"nofollow\" href=\"https:\/\/www.postgresql.org\/docs\/9.3\/functions-admin.html\">gendannelsesadministrationsfunktioner<\/a><\/noindex> (<code>pg_xlog_replay_pause(), pg_xlog_replay_resume()<\/code>) eller holde WAL-segmenterne i arkivet i en periode af forsinkelsen.<\/p>\n<p><\/p>\n<h3 id=\"kak-postgresql-eto-delaet\">Hvordan g\u00f8r PostgreSQL det?<\/h3>\n<p><\/p>\n<p>Det er interessant at se, hvordan PostgreSQL implementerer forsinket genopretning. Lad os se p\u00e5 <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>. Det kaldes fra <noindex><a rel=\"nofollow\" href=\"https:\/\/gitlab.com\/postgres\/postgres\/blob\/c24dcd0cfd949bdf245814c4c2b3df828ee7db36\/src\/backend\/access\/transam\/xlog.c#L7196\">den prim\u00e6re gentagelsescirkel<\/a><\/noindex> for hver post fra WAL.<\/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    \/* intet at g\u00f8re, hvis ingen forsinkelse er konfigureret *\/\n    if (recovery_min_apply_delay &lt;= 0)\n        return false;\n\n    \/* ingen forsinkelse anvendes p\u00e5 en database, der endnu ikke er konsistent *\/\n    if (!reachedConsistency)\n        return false;\n\n    \/*\n     * Er det en COMMIT post?\n     *\n     * Vi v\u00e6lger bevidst ikke at forsinke aborter, da de ikke p\u00e5virker\n     * MVCC. Vi tillader allerede gentagelse af poster, der ikke har et tidsstempel,\n     * s\u00e5 der er allerede mulighed for problemer for\u00e5rsaget af tidlige konflikter p\u00e5\n     * standby. \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     * Forlad uden at aktivere latches, hvis det allerede er forbi tid til at anvende denne\n     * post\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        \/\/ Forkortet:\n        \/\/ Brug WaitLatch, indtil vi n\u00e5r recoveryDelayUntilTime\n        \/\/ og s\u00e5\n        break;\n    }\n    return true;\n}<\/code><\/pre>\n<p><\/p>\n<p>Det er vigtigt, at forsinkelsen er baseret p\u00e5 det fysiske tidsstempel for transaktionens commit (<code>xtime<\/code>). Som det fremg\u00e5r, anvendes forsinkelsen kun p\u00e5 commits og p\u00e5virker ikke andre poster \u2014 alle \u00e6ndringer anvendes direkte, mens commit forsinkes, s\u00e5 vi f\u00f8rst ser \u00e6ndringerne efter den konfigurerede forsinkelse.<\/p>\n<p><\/p>\n<h3 id=\"kak-ispolzovat-otlozhennuyu-repliku-dlya-vosstanovleniya-dannyh\">S\u00e5dan bruger du en forsinket replika til at gendanne data<\/h3>\n<p><\/p>\n<p>Antag, at vi har et databasekluster i produktion og en replika med en otte timers forsinkelse. Lad os se, hvordan vi gendanner data som eksempel <noindex><a rel=\"nofollow\" href=\"https:\/\/gitlab.com\/gitlab-com\/gl-infra\/production\/issues\/509\">p\u00e5 en tilf\u00e6ldig sletning af genveje<\/a><\/noindex>.<\/p>\n<p><\/p>\n<p>Da vi fandt ud af problemet, <noindex><a rel=\"nofollow\" href=\"https:\/\/www.postgresql.org\/docs\/9.3\/functions-admin.html\">pausede vi gendannelsen fra arkivet<\/a><\/noindex> for den forsinkede replika:<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">SELECT pg_xlog_replay_pause();<\/code><\/pre>\n<p><\/p>\n<p>Med pausen var vi ikke i risiko for, at replikationen gentog anmodningen <code>DELETE<\/code>. En nyttig ting, hvis der er brug for tid til at finde ud af alt.<\/p>\n<p><\/p>\n<p>Pointen er, at den forsinkede replika skal n\u00e5 til tiden f\u00f8r anmodningen <code>DELETE<\/code>. Vi vidste nogenlunde det fysiske tidspunkt for sletningen. Vi slettede <code>recovery_min_apply_delay<\/code> og tilf\u00f8jede <code>recovery_target_time<\/code> i <code>recovery.conf<\/code>. S\u00e5 replikaen n\u00e5r det \u00f8nskede tidspunkt uden forsinkelser:<\/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>Med tidsstempler er det bedst at sk\u00e6re lidt fra, for ikke at g\u00e5 glip af noget. Men jo mere du sk\u00e6rer fra, jo mere data mister vi. Igen, hvis vi springer anmodningen over, <code>DELETE<\/code>vil alt blive slettet igen, og vi m\u00e5 starte forfra (eller tage en kold backup til PITR).<\/p>\n<p><\/p>\n<p>Vi genstartede den forsinkede Postgres-instans, og WAL-segmenterne blev gentaget indtil det angivne tidspunkt. Du kan spore fremskridtene p\u00e5 dette stadium ved at bruge foresp\u00f8rgslen:<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">SELECT\n  -- nuv\u00e6rende placering i WAL\n  pg_last_xlog_replay_location(),\n  -- aktuel transaktionstid (status for replikaen)\n  pg_last_xact_replay_timestamp(),\n  -- aktuel fysisk tid\n  now(),\n  -- den m\u00e6ngde tid, der stadig skal anvendes, indtil recovery_target_time er n\u00e5et\n  '2018-10-12 09:25:00+00'::timestamptz - pg_last_xact_replay_timestamp() as delay;<\/code><\/pre>\n<p><\/p>\n<p>Hvis tidsstemplet ikke l\u00e6ngere \u00e6ndrer sig, er gendannelsen afsluttet. Du kan indstille handlingen <noindex><a rel=\"nofollow\" href=\"https:\/\/www.postgresql.org\/docs\/current\/recovery-target-settings.html\"><code>recovery_target_action<\/code><\/a><\/noindex>, s\u00e5 du kan lukke, fremme eller s\u00e6tte instansen p\u00e5 pause efter gentagelsen (standardindstillingen er at s\u00e6tte den p\u00e5 pause).<\/p>\n<p><\/p>\n<p>Databasen er tilbage til tilstanden f\u00f8r den uheldige foresp\u00f8rgsel. Nu kan vi for eksempel eksportere data. Vi har eksporteret de slettede data om etiketter og deres relationer til opgaver og merge-foresp\u00f8rgsler og flyttet dem til den arbejdsbasen. Hvis tabet er omfattende, kan vi blot fremme replikaen og bruge den som hoveddatabase. Men s\u00e5 vil alle \u00e6ndringer efter det punkt, vi gendannede til, g\u00e5 tabt.<\/p>\n<p><\/p>\n<p>I stedet for tidsstempler er det bedre at bruge transaktions-ID'er. Det er nyttigt at notere disse ID'er, for eksempel for DDL-operat\u00f8rer (type <code>DROP TABLE<\/code>), ved hj\u00e6lp af <code>log_statements = 'ddl'<\/code>. Havde vi haft transaktions-ID'et, ville vi have taget <code>recovery_target_xid<\/code> og k\u00f8rt alle transaktioner op til transaktionen f\u00f8r foresp\u00f8rgslen. <code>DELETE<\/code>.<\/p>\n<p><\/p>\n<p>Det er meget nemt at komme tilbage til arbejdet: fjern alle \u00e6ndringer fra <code>recovery.conf<\/code> og genstart Postgres. Snart vil der igen v\u00e6re en otte timers forsinkelse i replikaen, og vi er klar til fremtidige problemer.<\/p>\n<p><\/p>\n<h3 id=\"preimuschestva-dlya-vosstanovleniya\">Fordele ved gendannelse<\/h3>\n<p><\/p>\n<p>Med en forsinket replica i stedet for en kold backup slipper vi for timer med at gendanne hele snapshotet fra arkivet. For eksempel tager det os fem timer at hente hele basisbackupen p\u00e5 2 TB. Og s\u00e5 skal vi ogs\u00e5 anvende hele den daglige WAL for at komme tilbage til den \u00f8nskede tilstand (i v\u00e6rste tilf\u00e6lde).<\/p>\n<p><\/p>\n<p>En forsinket replica er bedre end en kold backup af to grunde:<\/p>\n<p><\/p>\n<ol>\n<li>Vi skal ikke hente hele basisbackupen fra arkivet.<\/li>\n<li>Der er et fast otte timers vindue for WAL-segmenter, der skal gentages.<\/li>\n<\/ol>\n<p><\/p>\n<p>Og vi kontrollerer konstant, om det er muligt at udf\u00f8re PITR fra WAL, og vi ville hurtigt bem\u00e6rke skader eller andre problemer med WAL-arkivet ved at overv\u00e5ge forsinkelsen p\u00e5 den forsinkede replica.<\/p>\n<p><\/p>\n<p>I dette eksempel tog det os 50 minutter at gendanne, hvilket betyder, at hastigheden var 110 GB WAL-data i timen (arkivet var stadig p\u00e5 <noindex><a rel=\"nofollow\" href=\"https:\/\/aws.amazon.com\/s3\/\">AWS S3<\/a><\/noindex>). I alt lykkedes vi at l\u00f8se problemet og genskabe dataene p\u00e5 1,5 time.<\/p>\n<p><\/p>\n<h3 id=\"itogi-gde-prigoditsya-otlozhennaya-replika-a-gde-net\">Konklusioner: hvor det er nyttigt med forsinket replikation (og hvor det ikke er)<\/h3>\n<p><\/p>\n<p>Brug forsinket replikation som en n\u00f8dplan, hvis du ved en fejl har mistet data og opdager fejlen inden for den indstillede forsinkelse.<\/p>\n<p><\/p>\n<blockquote><p>Men husk: replikation er ikke en backup.<\/p><\/blockquote>\n<p>Backup og replikation har forskellige form\u00e5l. En kold backup er nyttig, hvis du ved en fejl har lavet <code>DELETE<\/code> eller <code>DROP TABLE<\/code>. Vi laver en backup fra det kolde lager og genskaber den tidligere tilstand for tabellen eller hele databasen. Men foresp\u00f8rgslen <code>DROP TABLE<\/code> replikeres n\u00e6sten \u00f8jeblikkeligt til alle replikater i arbejdsclusteret, s\u00e5 almindelig replikation vil ikke redde dig her. Replikation i sig selv holder databasen tilg\u00e6ngelig, n\u00e5r enkelte servere er nede, og fordeler belastningen.<\/p>\n<p><\/p>\n<p>Selv med en forsinket replikation har vi nogle gange brug for en kold backup p\u00e5 et sikkert sted, hvis der pludselig opst\u00e5r fejl i datacentret, skjult beskadigelse eller andre h\u00e6ndelser, som du ikke straks bem\u00e6rker. Her er replikation alene ikke tilstr\u00e6kkelig.<\/p>\n<p><\/p>\n<p><strong>Bem\u00e6rk<\/strong>. P\u00e5 <noindex><a rel=\"nofollow\" href=\"https:\/\/gitlab.com\/\">GitLab.com<\/a><\/noindex> vi beskytter i \u00f8jeblikket kun mod datatab p\u00e5 systemniveau og genskaber ikke data p\u00e5 brugerniveau.<\/p>\n<p>Kilde: <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.3 - 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\/da\/blog\/administrirovanie\/kak-my-ispolzovali-otlozhennuyu-replikatsiyu-dlya-avarijnogo-vosstanovleniya-s-postgresql\" \/>\n\t\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.3\" \/>\n\t\t<meta property=\"og:locale\" content=\"da_DK\" \/>\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\/da\/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\udd47Hvordan vi brugte forsinket replikation til n\u00f8dfindelse med PostgreSQL | ProHoster","description":".","canonical_url":"https:\/\/prohoster.info\/da\/blog\/administrirovanie\/kak-my-ispolzovali-otlozhennuyu-replikatsiyu-dlya-avarijnogo-vosstanovleniya-s-postgresql","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"da_DK","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\/da\/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\/da\/wp-json\/wp\/v2\/posts\/30356","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/da\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/da\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/da\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/da\/wp-json\/wp\/v2\/comments?post=30356"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/da\/wp-json\/wp\/v2\/posts\/30356\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/da\/wp-json\/wp\/v2\/media\/22360"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/da\/wp-json\/wp\/v2\/media?parent=30356"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/da\/wp-json\/wp\/v2\/categories?post=30356"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/da\/wp-json\/wp\/v2\/tags?post=30356"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}