{"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\/pt\/blog\/administrirovanie\/kak-my-ispolzovali-otlozhennuyu-replikatsiyu-dlya-avarijnogo-vosstanovleniya-s-postgresql","title":{"rendered":"Como usamos a replica\u00e7\u00e3o atrasada para recupera\u00e7\u00e3o de desastres com PostgreSQL","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p><img decoding=\"async\" alt=\"Como usamos a replica\u00e7\u00e3o atrasada para recupera\u00e7\u00e3o de desastres com PostgreSQL\" src=\"\/wp-content\/uploads\/2019\/03\/773f3b6c8d173be91c49066d7067bad3.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nA replica\u00e7\u00e3o n\u00e3o \u00e9 um backup. Ou \u00e9? Veja como usamos a replica\u00e7\u00e3o atrasada para recupera\u00e7\u00e3o ap\u00f3s deletar acidentalmente os atalhos.<\/p>\n<p><\/p>\n<p><noindex><a rel=\"nofollow\" href=\"https:\/\/about.gitlab.com\/handbook\/engineering\/infrastructure\/\">Especialistas em infraestrutura<\/a><\/noindex> no GitLab s\u00e3o respons\u00e1veis pela opera\u00e7\u00e3o <noindex><a rel=\"nofollow\" href=\"https:\/\/gitlab.com\/\">GitLab.com<\/a><\/noindex> \u2014 a maior inst\u00e2ncia do GitLab no mundo. Aqui est\u00e3o 3 milh\u00f5es de usu\u00e1rios e quase 7 milh\u00f5es de projetos, sendo um dos maiores sites de SaaS de c\u00f3digo aberto com arquitetura dedicada. Sem o sistema de banco de dados PostgreSQL, a infraestrutura do GitLab.com n\u00e3o iria longe, e fazemos o que for necess\u00e1rio para garantir a resili\u00eancia em casos de falha, quando dados podem ser perdidos. \u00c9 improv\u00e1vel que tal cat\u00e1strofe aconte\u00e7a, mas estamos bem preparados e temos diversos mecanismos de backup e replica\u00e7\u00e3o.<\/p>\n<p><\/p>\n<p>A replica\u00e7\u00e3o n\u00e3o \u00e9 uma solu\u00e7\u00e3o de backup de banco de dados (<noindex><a rel=\"nofollow\" href=\"https:\/\/about.gitlab.com\/2019\/02\/13\/delayed-replication-for-disaster-recovery-with-postgresql\/#summing-up\">veja abaixo<\/a><\/noindex>). Mas agora veremos como recuperar rapidamente dados exclu\u00eddos acidentalmente com a ajuda da replica\u00e7\u00e3o atrasada: quando um <noindex><a rel=\"nofollow\" href=\"https:\/\/gitlab.com\/\">GitLab.com<\/a><\/noindex> usu\u00e1rio <noindex><a rel=\"nofollow\" href=\"https:\/\/gitlab.com\/gitlab-com\/gl-infra\/production\/issues\/509\">excluiu um atalho<\/a><\/noindex> para o projeto <noindex><a rel=\"nofollow\" href=\"https:\/\/gitlab.com\/gitlab-org\/gitlab-ce\/\"><code>gitlab-ce<\/code><\/a><\/noindex> e perdeu a conex\u00e3o com as solicita\u00e7\u00f5es de mesclagem e tarefas.<\/p>\n<p><\/p>\n<p>Com a replica\u00e7\u00e3o atrasada, recuperamos os dados em apenas 1,5 horas. Veja como isso aconteceu.<\/p>\n<p><noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<h3 id=\"vosstanovlenie-na-moment-vremeni-s-postgresql\">Recupera\u00e7\u00e3o em um ponto no tempo com PostgreSQL<\/h3>\n<p><\/p>\n<p>O PostgreSQL possui uma fun\u00e7\u00e3o embutida que restaura o estado do banco de dados em um determinado ponto no tempo. Ela \u00e9 chamada <noindex><a rel=\"nofollow\" href=\"https:\/\/www.postgresql.org\/docs\/current\/continuous-archiving.html\">Recupera\u00e7\u00e3o de Ponto no Tempo<\/a><\/noindex> (PITR) e utiliza os mesmos mecanismos que mant\u00eam a replica\u00e7\u00e3o atualizada: come\u00e7ando com uma captura confi\u00e1vel de todo o cluster de banco de dados (backup base), aplicamos uma s\u00e9rie de altera\u00e7\u00f5es at\u00e9 um ponto no tempo espec\u00edfico.<\/p>\n<p><\/p>\n<p>Para usar essa fun\u00e7\u00e3o para um backup frio, fazemos backups base do banco de dados regularmente e o armazenamos em um arquivo (os arquivos do GitLab vivem em <noindex><a rel=\"nofollow\" href=\"https:\/\/cloud.google.com\/storage\/\">armazenamento em nuvem do Google<\/a><\/noindex>). Al\u00e9m disso, monitoramos as altera\u00e7\u00f5es de estado do banco de dados, arquivando o log de grava\u00e7\u00e3o antecipada (<noindex><a rel=\"nofollow\" href=\"https:\/\/www.postgresql.org\/docs\/current\/wal-intro.html\">write-ahead log<\/a><\/noindex>, WAL). Com tudo isso, podemos realizar a PITR para recupera\u00e7\u00e3o de desastres: come\u00e7amos com a captura feita antes do erro e aplicamos as altera\u00e7\u00f5es do arquivo WAL at\u00e9 a falha.<\/p>\n<p><\/p>\n<h3 id=\"chto-takoe-otlozhennaya-replikaciya\">O que \u00e9 replica\u00e7\u00e3o atrasada?<\/h3>\n<p><\/p>\n<p>A replica\u00e7\u00e3o atrasada \u00e9 a aplica\u00e7\u00e3o de altera\u00e7\u00f5es do WAL com um atraso. Ou seja, a transa\u00e7\u00e3o ocorreu na hora <code>X<\/code>, mas na replica\u00e7\u00e3o ela aparecer\u00e1 com um atraso <code>d<\/code> de uma hora <code>X + d<\/code>.<\/p>\n<p><\/p>\n<p>No PostgreSQL, existem 2 maneiras de configurar a replica\u00e7\u00e3o f\u00edsica do banco de dados: recupera\u00e7\u00e3o a partir de um arquivo e replica\u00e7\u00e3o em streaming. <noindex><a rel=\"nofollow\" href=\"https:\/\/www.postgresql.org\/docs\/current\/archive-recovery-settings.html\">Recupera\u00e7\u00e3o a partir de um arquivo<\/a><\/noindex>, na verdade, funciona como PITR, mas de forma cont\u00ednua: estamos constantemente extraindo mudan\u00e7as do arquivo WAL e aplicando-as na r\u00e9plica. A <noindex><a rel=\"nofollow\" href=\"https:\/\/wiki.postgresql.org\/wiki\/Streaming_Replication\">replica\u00e7\u00e3o streaming<\/a><\/noindex> extrai diretamente o fluxo WAL do host de banco de dados superior. Preferimos a recupera\u00e7\u00e3o a partir do arquivo \u2014 \u00e9 mais f\u00e1cil de gerenciar e tem um desempenho normal que n\u00e3o fica aqu\u00e9m do cluster de trabalho.<\/p>\n<p><\/p>\n<h3 id=\"kak-nastroit-otlozhennoe-vosstanovlenie-iz-arhiva\">Como configurar a recupera\u00e7\u00e3o atrasada a partir do arquivo<\/h3>\n<p><\/p>\n<p><noindex><a rel=\"nofollow\" href=\"https:\/\/www.postgresql.org\/docs\/current\/recovery-config.html\">Op\u00e7\u00f5es de recupera\u00e7\u00e3o<\/a><\/noindex> est\u00e3o descritas no arquivo <code>recovery.conf<\/code>. Exemplo:<\/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>Com essas configura\u00e7\u00f5es, configuramos a r\u00e9plica atrasada com recupera\u00e7\u00e3o a partir do arquivo. Aqui usamos <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/wal-e\/wal-e\">wal-e<\/a><\/noindex> para extrair os segmentos WAL (<code>restore_command<\/code>) do arquivo, e as mudan\u00e7as ser\u00e3o aplicadas ap\u00f3s oito horas (<code>recovery_min_apply_delay<\/code>). A r\u00e9plica ir\u00e1 monitorar as mudan\u00e7as na linha do tempo do arquivo, por exemplo, devido a uma falha no cluster (<code>recovery_target_timeline<\/code>).<\/p>\n<p><\/p>\n<p>Com <code>recovery_min_apply_delay<\/code> \u00e9 poss\u00edvel configurar a replica\u00e7\u00e3o streaming com atraso, mas h\u00e1 algumas pegadinhas que envolvem slots de replica\u00e7\u00e3o, feedback de failover e outros. O arquivo WAL permite evit\u00e1-las.<\/p>\n<p><\/p>\n<p>Par\u00e2metro <code>recovery_min_apply_delay<\/code> apareceu apenas no PostgreSQL 9.3. Em vers\u00f5es anteriores, para replica\u00e7\u00e3o atrasada, era necess\u00e1rio configurar uma combina\u00e7\u00e3o de <noindex><a rel=\"nofollow\" href=\"https:\/\/www.postgresql.org\/docs\/9.3\/functions-admin.html\">fun\u00e7\u00f5es de controle de recupera\u00e7\u00e3o<\/a><\/noindex> (<code>pg_xlog_replay_pause(), pg_xlog_replay_resume()<\/code>) ou manter os segmentos WAL no arquivo durante o tempo de atraso.<\/p>\n<p><\/p>\n<h3 id=\"kak-postgresql-eto-delaet\">Como o PostgreSQL faz isso?<\/h3>\n<p><\/p>\n<p>\u00c9 interessante ver como o PostgreSQL implementa a recupera\u00e7\u00e3o atrasada. Vamos olhar para <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>. Ele \u00e9 chamado no <noindex><a rel=\"nofollow\" href=\"https:\/\/gitlab.com\/postgres\/postgres\/blob\/c24dcd0cfd949bdf245814c4c2b3df828ee7db36\/src\/backend\/access\/transam\/xlog.c#L7196\">loop principal de repeti\u00e7\u00e3o<\/a><\/noindex> para cada registro do 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    \/* nada para fazer se nenhuma demora estiver configurada *\/\n    if (recovery_min_apply_delay &lt;= 0)\n        return false;\n\n    \/* nenhuma demora \u00e9 aplicada em um banco de dados que ainda n\u00e3o est\u00e1 consistente *\/\n    if (!reachedConsistency)\n        return false;\n\n    \/*\n     * \u00c9 um registro de COMMIT?\n     *\n     * Escolhemos deliberadamente n\u00e3o atrasar abortos, pois eles n\u00e3o t\u00eam efeito sobre\n     * MVCC. J\u00e1 permitimos a reprodu\u00e7\u00e3o de registros que n\u00e3o t\u00eam um timestamp,\n     * ent\u00e3o j\u00e1 h\u00e1 oportunidades para problemas causados por conflitos precoces em\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     * Saia sem armar o latch se j\u00e1 estiver passado o tempo para aplicar este\n     * registro\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        \/\/ Encurtado:\n        \/\/ Use WaitLatch at\u00e9 alcanzarmos recoveryDelayUntilTime\n        \/\/ e ent\u00e3o\n        break;\n    }\n    return true;\n}<\/code><\/pre>\n<p><\/p>\n<p>O fato \u00e9 que a demora \u00e9 baseada no tempo f\u00edsico registrado no timestamp do commit da transa\u00e7\u00e3o (<code>xtime<\/code>). Como pode ser visto, a demora se aplica apenas a commits e n\u00e3o afeta outros registros \u2014 todas as altera\u00e7\u00f5es s\u00e3o aplicadas diretamente, enquanto o commit \u00e9 adiado, assim veremos as altera\u00e7\u00f5es apenas ap\u00f3s o atraso configurado.<\/p>\n<p><\/p>\n<h3 id=\"kak-ispolzovat-otlozhennuyu-repliku-dlya-vosstanovleniya-dannyh\">Como usar uma r\u00e9plica atrasada para recupera\u00e7\u00e3o de dados<\/h3>\n<p><\/p>\n<p>Vamos supor que temos um cluster de banco de dados em produ\u00e7\u00e3o e uma r\u00e9plica com um atraso de oito horas. Vamos ver como recuperar dados usando o exemplo <noindex><a rel=\"nofollow\" href=\"https:\/\/gitlab.com\/gitlab-com\/gl-infra\/production\/issues\/509\">de uma exclus\u00e3o acidental de atalhos<\/a><\/noindex>.<\/p>\n<p><\/p>\n<p>Quando soubemos do problema, n\u00f3s <noindex><a rel=\"nofollow\" href=\"https:\/\/www.postgresql.org\/docs\/9.3\/functions-admin.html\">pausamos a recupera\u00e7\u00e3o do arquivo<\/a><\/noindex> para a r\u00e9plica atrasada:<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">SELECT pg_xlog_replay_pause();<\/code><\/pre>\n<p><\/p>\n<p>Com a pausa n\u00e3o havia risco de a r\u00e9plica repetir a solicita\u00e7\u00e3o <code>DELETE<\/code>. Uma coisa \u00fatil, se voc\u00ea precisar de tempo para investigar tudo.<\/p>\n<p><\/p>\n<p>O ponto \u00e9 que a r\u00e9plica atrasada deve chegar ao momento anterior \u00e0 solicita\u00e7\u00e3o <code>DELETE<\/code>. Sab\u00edamos mais ou menos o tempo f\u00edsico da exclus\u00e3o. N\u00f3s exclu\u00edmos <code>recovery_min_apply_delay<\/code> e adicionamos <code>recovery_target_time<\/code> em <code>recovery.conf<\/code>. Assim, a r\u00e9plica chega ao momento correto sem atrasos:<\/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>Com timestamps, \u00e9 melhor reduzir o que for excessivo, para n\u00e3o errar. Por\u00e9m, quanto mais reduzirmos, mais dados perdemos. Novamente, se pul\u00e1ssemos a solicita\u00e7\u00e3o <code>DELETE<\/code>, tudo seria exclu\u00eddo novamente e ter\u00edamos que come\u00e7ar do zero (ou at\u00e9 mesmo pegar um backup frio para PITR).<\/p>\n<p><\/p>\n<p>Reiniciamos a inst\u00e2ncia atrasada do Postgres e os segmentos WAL se repetiram at\u00e9 o hor\u00e1rio indicado. O progresso nesta fase pode ser acompanhado pela consulta:<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">SELECT\n  -- localiza\u00e7\u00e3o atual no WAL\n  pg_last_xlog_replay_location(),\n  -- timestamp da transa\u00e7\u00e3o atual (estado da r\u00e9plica)\n  pg_last_xact_replay_timestamp(),\n  -- tempo f\u00edsico atual\n  now(),\n  -- a quantidade de tempo que ainda precisa ser aplicada at\u00e9 que recovery_target_time seja alcan\u00e7ado\n  '2018-10-12 09:25:00+00'::timestamptz - pg_last_xact_replay_timestamp() as delay;<\/code><\/pre>\n<p><\/p>\n<p>Se o timestamp n\u00e3o mudar mais, a recupera\u00e7\u00e3o est\u00e1 conclu\u00edda. Voc\u00ea pode configurar a a\u00e7\u00e3o <noindex><a rel=\"nofollow\" href=\"https:\/\/www.postgresql.org\/docs\/current\/recovery-target-settings.html\"><code>recovery_target_action<\/code><\/a><\/noindex>, para fechar, avan\u00e7ar ou pausar a inst\u00e2ncia ap\u00f3s a repeti\u00e7\u00e3o (por padr\u00e3o, ela \u00e9 pausada).<\/p>\n<p><\/p>\n<p>O banco de dados voltou ao estado antes daquela consulta infeliz. Agora voc\u00ea pode, por exemplo, exportar dados. Exportamos os dados removidos do atalho e todas as rela\u00e7\u00f5es com as tarefas e merge requests e os transferimos para o banco de dados ativo. Se as perdas forem significativas, voc\u00ea pode simplesmente avan\u00e7ar a r\u00e9plica e us\u00e1-la como principal. Mas, nesse caso, todas as altera\u00e7\u00f5es ap\u00f3s o momento at\u00e9 o qual nos recuperamos ser\u00e3o perdidas.<\/p>\n<p><\/p>\n<p>Em vez de timestamps, \u00e9 melhor usar IDs de transa\u00e7\u00f5es. \u00c9 \u00fatil registrar esses IDs, por exemplo, para operadores DDL (como <code>DROP TABLE<\/code>), com o aux\u00edlio de <code>log_statements = 'ddl'<\/code>. Se tiv\u00e9ssemos o ID da transa\u00e7\u00e3o, pegar\u00edamos <code>recovery_target_xid<\/code> e executar\u00edamos todos at\u00e9 a transa\u00e7\u00e3o anterior \u00e0 consulta. <code>DELETE<\/code>.<\/p>\n<p><\/p>\n<p>Voltar ao trabalho \u00e9 muito simples: remova todas as altera\u00e7\u00f5es de <code>recovery.conf<\/code> e reinicie o Postgres. Em breve, a r\u00e9plica ter\u00e1 novamente um atraso de oito horas, e estaremos prontos para futuros contratempos.<\/p>\n<p><\/p>\n<h3 id=\"preimuschestva-dlya-vosstanovleniya\">Vantagens para recupera\u00e7\u00e3o<\/h3>\n<p><\/p>\n<p>Com uma r\u00e9plica atrasada em vez de um backup frio, n\u00e3o precisamos passar horas restaurando toda a captura do arquivo. Por exemplo, n\u00f3s precisamos de cinco horas para obter todo o backup base de 2 TB. E depois ainda precisamos aplicar todo o WAL di\u00e1rio para recuperar o estado desejado (no pior cen\u00e1rio).<\/p>\n<p><\/p>\n<p>A r\u00e9plica atrasada \u00e9 melhor do que o backup frio por dois motivos:<\/p>\n<p><\/p>\n<ol>\n<li>N\u00e3o precisamos retirar todo o backup base do arquivo.<\/li>\n<li>H\u00e1 uma janela fixa de oito horas de segmentos WAL que precisam ser repetidos.<\/li>\n<\/ol>\n<p><\/p>\n<p>Al\u00e9m disso, estamos constantemente verificando se podemos fazer PITR a partir do WAL, e notar\u00edamos rapidamente quaisquer danos ou outros problemas com o arquivo WAL, monitorando o atraso da r\u00e9plica atrasada.<\/p>\n<p><\/p>\n<p>Neste exemplo, levamos 50 minutos para recuperar, ou seja, a velocidade foi de 110 GB de dados WAL por hora (o arquivo ainda estava em <noindex><a rel=\"nofollow\" href=\"https:\/\/aws.amazon.com\/s3\/\">AWS S3<\/a><\/noindex>). No total resolvemos o problema e restauramos os dados em 1,5 horas.<\/p>\n<p><\/p>\n<h3 id=\"itogi-gde-prigoditsya-otlozhennaya-replika-a-gde-net\">Resultados: onde a replica\u00e7\u00e3o atrasada \u00e9 \u00fatil (e onde n\u00e3o \u00e9)<\/h3>\n<p><\/p>\n<p>Use a replica\u00e7\u00e3o atrasada como uma medida de emerg\u00eancia se voc\u00ea acidentalmente perdeu dados e percebeu isso dentro da janela de atraso configurada.<\/p>\n<p><\/p>\n<blockquote><p>Mas tenha em mente: replica\u00e7\u00e3o n\u00e3o \u00e9 backup.<\/p><\/blockquote>\n<p>Backup e replica\u00e7\u00e3o t\u00eam objetivos diferentes. Um backup frio \u00e9 \u00fatil se voc\u00ea acidentalmente fez <code>DELETE<\/code> ou <code>DROP TABLE<\/code>. Fazemos backup do armazenamento frio e restauramos o estado anterior da tabela ou de todo o banco de dados. Mas nesse caso, a consulta <code>DROP TABLE<\/code> \u00e9 quase instantaneamente replicada em todas as r\u00e9plicas do cluster de trabalho, portanto, a replica\u00e7\u00e3o comum n\u00e3o salvar\u00e1 a situa\u00e7\u00e3o. A replica\u00e7\u00e3o, por si s\u00f3, mant\u00e9m o banco de dados acess\u00edvel, quando servidores individuais falham, e distribui a carga.<\/p>\n<p><\/p>\n<p>Mesmo com a replica\u00e7\u00e3o atrasada, muitas vezes precisamos de um backup frio em um local seguro, caso ocorra uma falha de data center, uma corrup\u00e7\u00e3o oculta ou outros eventos que n\u00e3o sejam percebidos imediatamente. Aqui, apenas a replica\u00e7\u00e3o n\u00e3o \u00e9 suficiente.<\/p>\n<p><\/p>\n<p><strong>Nota<\/strong>. No <noindex><a rel=\"nofollow\" href=\"https:\/\/gitlab.com\/\">GitLab.com<\/a><\/noindex> Atualmente, estamos protegendo contra a perda de dados apenas no n\u00edvel do sistema e n\u00e3o recuperamos os dados no n\u00edvel do usu\u00e1rio.<\/p>\n<p>Fonte: <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\/pt\/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=\"pt_PT\" \/>\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\/pt\/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\udd47Como usamos a replica\u00e7\u00e3o atrasada para recupera\u00e7\u00e3o de desastres com PostgreSQL | ProHoster","description":".","canonical_url":"https:\/\/prohoster.info\/pt\/blog\/administrirovanie\/kak-my-ispolzovali-otlozhennuyu-replikatsiyu-dlya-avarijnogo-vosstanovleniya-s-postgresql","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"pt_PT","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\/pt\/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\/pt\/wp-json\/wp\/v2\/posts\/30356","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/pt\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/pt\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/pt\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/pt\/wp-json\/wp\/v2\/comments?post=30356"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/pt\/wp-json\/wp\/v2\/posts\/30356\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/pt\/wp-json\/wp\/v2\/media\/22360"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/pt\/wp-json\/wp\/v2\/media?parent=30356"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/pt\/wp-json\/wp\/v2\/categories?post=30356"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/pt\/wp-json\/wp\/v2\/tags?post=30356"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}