PostgreSQL рд╕рд╣ рдЖрдкрддреНрддреА рдкреБрдирд░реНрдкреНрд░рд╛рдкреНрддреАрд╕рд╛рдареА рдЖрд│рд╢реА рдкреНрд░рддрд┐рдХреГрддреА рдХрд╢реА рд╡рд╛рдкрд░рд▓реА

PostgreSQL рд╕рд╣ рдЖрдкрддреНрддреА рдкреБрдирд░реНрдкреНрд░рд╛рдкреНрддреАрд╕рд╛рдареА рдЖрд│рд╢реА рдкреНрд░рддрд┐рдХреГрддреА рдХрд╢реА рд╡рд╛рдкрд░рд▓реА
рдкреНрд░рддрд┐рдХреГрддреА рдмреЕрдХрдЕрдк рдирд╛рд╣реА. рдХрд┐рдВрд╡рд╛ рдирд╛рд╣реА? рдЪреБрдХреВрди рд╣рдЯрд╡рд▓реЗрд▓реНрдпрд╛ рд╢реЙрд░реНрдЯрдХрдЯрдордзреВрди рдкреБрдирд░реНрдкреНрд░рд╛рдкреНрдд рдХрд░рдгреНрдпрд╛рд╕рд╛рдареА рдЖрдореНрд╣реА рдкреБрдвреЗ рдврдХрд▓рд▓реЗрд▓реА рдкреНрд░рддрд┐рдХреГрддреА рдХрд╢реА рд╡рд╛рдкрд░рд▓реА рддреЗ рдпреЗрдереЗ рдЖрд╣реЗ.

рдкрд╛рдпрд╛рднреВрдд рд╕реБрд╡рд┐рдзрд╛ рддрдЬреНрдЮ GitLab рдпрд╛ рдХрд╛рдорд╛рд╕рд╛рдареА рдЬрдмрд╛рдмрджрд╛рд░ рдЖрд╣реЗ GitLab.com - рдирд┐рд╕рд░реНрдЧрд╛рддреАрд▓ рд╕рд░реНрд╡рд╛рдд рдореЛрдареА GitLab рдЙрджрд╛рд╣рд░рдг. 3 рджрд╢рд▓рдХреНрд╖ рд╡рд╛рдкрд░рдХрд░реНрддреЗ рдЖрдгрд┐ рд╕реБрдорд╛рд░реЗ 7 рджрд╢рд▓рдХреНрд╖ рдкреНрд░рдХрд▓реНрдкрд╛рдВрд╕рд╣, рд╣реА рд╕рдорд░реНрдкрд┐рдд рдЖрд░реНрдХрд┐рдЯреЗрдХреНрдЪрд░рд╕рд╣ рд╕рд░реНрд╡рд╛рдд рдореЛрдареА рдореБрдХреНрдд рд╕реНрд░реЛрдд SaaS рд╕рд╛рдЗрдЯ рдЖрд╣реЗ. PostgreSQL рдбреЗрдЯрд╛рдмреЗрд╕ рд╕рд┐рд╕реНрдЯреАрдо рд╢рд┐рд╡рд╛рдп, GitLab.com рдкрд╛рдпрд╛рднреВрдд рд╕реБрд╡рд┐рдзрд╛ рдлрд╛рд░ рдкреБрдвреЗ рдЬрд╛рдгрд╛рд░ рдирд╛рд╣реА рдЖрдгрд┐ рдбреЗрдЯрд╛ рд╣рд░рд╡рд▓реНрдпрд╛рд╕ рдХреЛрдгрддреНрдпрд╛рд╣реА рдмрд┐рдШрд╛рдб рдЭрд╛рд▓реНрдпрд╛рд╕ рдлреЙрд▓реНрдЯ рдЯреЙрд▓рд░рдиреНрд╕ рд╕реБрдирд┐рд╢реНрдЪрд┐рдд рдХрд░рдгреНрдпрд╛рд╕рд╛рдареА рдЖрдореНрд╣реА рдХрд╛рдп рдХрд░рдд рдЖрд╣реЛрдд. рдЕрд╢реА рдЖрдкрддреНрддреА рдШрдбрдгреНрдпрд╛рдЪреА рд╢рдХреНрдпрддрд╛ рдирд╛рд╣реА, рдкрд░рдВрддреБ рдЖрдореНрд╣реА рд╡рд┐рд╡рд┐рдз рдмреЕрдХрдЕрдк рдЖрдгрд┐ рдкреНрд░рддрд┐рдХреГрддреА рдпрдВрддреНрд░рдгреЗрд╕рд╣ рддрдпрд╛рд░ рдЖрдгрд┐ рд╕рд╛рдард╛ рдХреЗрд▓реЗрд▓рд╛ рдЖрд╣реЗ.

рдкреНрд░рддрд┐рдХреГрддреА рд╣реЗ рдбреЗрдЯрд╛рдмреЗрд╕рдЪрд╛ рдмреЕрдХрдЕрдк рдШреЗрдгреНрдпрд╛рдЪреЗ рд╕рд╛рдзрди рдирд╛рд╣реА (рдЦрд╛рд▓реА рдкрд╣рд╛). рдкрдг рдЖрддрд╛ рдЖрд│рд╢реА рдкреНрд░рддрд┐рдХреГрддреА рд╡рд╛рдкрд░реВрди рдЪреБрдХреВрди рд╣рдЯрд╡рд▓реЗрд▓рд╛ рдбреЗрдЯрд╛ рддреНрд╡рд░реАрдд рдХрд╕рд╛ рдкреБрдирд░реНрдкреНрд░рд╛рдкреНрдд рдХрд░рд╛рдпрдЪрд╛ рддреЗ рдЖрдкрдг рдкрд╛рд╣реВ: рдЪрд╛рд▓реВ GitLab.com рд╡рд╛рдкрд░рдХрд░реНрддрд╛ рд╢реЙрд░реНрдЯрдХрдЯ рд╣рдЯрд╡рд▓рд╛ рдкреНрд░рдХрд▓реНрдкрд╛рд╕рд╛рдареА gitlab-ce рдЖрдгрд┐ рд╡рд┐рд▓реАрди рд╡рд┐рдирдВрддреНрдпрд╛ рдЖрдгрд┐ рдХрд╛рд░реНрдпрд╛рдВрд╕рд╣ рдХрдиреЗрдХреНрд╢рди рдЧрдорд╛рд╡рд▓реЗ.

рд╕реНрдердЧрд┐рдд рдкреНрд░рддрд┐рдХреГрддреАрд╕рд╣, рдЖрдореНрд╣реА рдлрдХреНрдд 1,5 рддрд╛рд╕рд╛рдВрдордзреНрдпреЗ рдбреЗрдЯрд╛ рдкреБрдирд░реНрдкреНрд░рд╛рдкреНрдд рдХреЗрд▓рд╛. рддреЗ рдХрд╕реЗ рдШрдбрд▓реЗ рддреЗ рдкрд╣рд╛.

PostgreSQL рд╕рд╣ рдкреЙрдЗрдВрдЯ рдЗрди рдЯрд╛рдЗрдо рд░рд┐рдХрд╡реНрд╣рд░реА

PostgreSQL рдордзреНрдпреЗ рдПрдХ рдЕрдВрдЧрднреВрдд рдлрдВрдХреНрд╢рди рдЖрд╣реЗ рдЬреЗ рдбреЗрдЯрд╛рдмреЗрд╕рдЪреА рд╕реНрдерд┐рддреА рд╡реЗрд│реЗрдд рд╡рд┐рд╢рд┐рд╖реНрдЯ рдмрд┐рдВрджреВрд╡рд░ рдкреБрдирд░реНрд╕рдВрдЪрдпрд┐рдд рдХрд░рддреЗ. рдЕрд╕реЗ рдореНрд╣рдгрддрд╛рдд рдкреЙрдЗрдВрдЯ-рдЗрди-рдЯрд╛рдЗрдо рдкреБрдирд░реНрдкреНрд░рд╛рдкреНрддреА (PITR) рдЖрдгрд┐ рддреАрдЪ рдпрдВрддреНрд░рдгрд╛ рд╡рд╛рдкрд░рддреЗ рдЬреА рдкреНрд░рддрд┐рдХреГрддреА рдЕрджреНрдпрдпрд╛рд╡рдд рдареЗрд╡рддреЗ: рд╕рдВрдкреВрд░реНрдг рдбреЗрдЯрд╛рдмреЗрд╕ рдХреНрд▓рд╕реНрдЯрд░рдЪреНрдпрд╛ (рдмреЗрд╕ рдмреЕрдХрдЕрдк) рд╡рд┐рд╢реНрд╡рд╛рд╕рд╛рд░реНрд╣ рд╕реНрдиреЕрдкрд╢реЙрдЯрд╕рд╣ рдкреНрд░рд╛рд░рдВрдн рдХрд░реВрди, рдЖрдореНрд╣реА рдПрдХрд╛ рд╡рд┐рд╢рд┐рд╖реНрдЯ рдмрд┐рдВрджреВрдкрд░реНрдпрдВрдд рд░рд╛рдЬреНрдп рдмрджрд▓рд╛рдВрдЪреА рдорд╛рд▓рд┐рдХрд╛ рд▓рд╛рдЧреВ рдХрд░рддреЛ.

рдХреЛрд▓реНрдб рдмреЕрдХрдЕрдкрд╕рд╛рдареА рд╣реЗ рд╡реИрд╢рд┐рд╖реНрдЯреНрдп рд╡рд╛рдкрд░рдгреНрдпрд╛рд╕рд╛рдареА, рдЖрдореНрд╣реА рдирд┐рдпрдорд┐рддрдкрдгреЗ рдмреЗрд╕рд┐рдХ рдбреЗрдЯрд╛рдмреЗрд╕ рдмреЕрдХрдЕрдк рдмрдирд╡рддреЛ рдЖрдгрд┐ рд╕рдВрдЧреНрд░рд╣рдгрд╛рдд рд╕рдВрдЧреНрд░рд╣рд┐рдд рдХрд░рддреЛ (GitLab рд╕рдВрдЧреНрд░рд╣рдг Google рдХреНрд▓рд╛рдЙрдб рд╕реНрдЯреЛрд░реЗрдЬ). рдЖрдореНрд╣реА рд░рд╛рдИрдЯ-рдЕрд╣реЗрдб рд▓реЙрдЧ (рд▓рд┐рд╣рд╛-рдкреБрдвреЗ рд▓реЙрдЧ, WAL). рдЖрдгрд┐ рдпрд╛ рд╕рд░реНрд╡ рдард┐рдХрд╛рдгреА, рдЖрдореНрд╣реА рдЖрдкрддреНрддреА рдкреБрдирд░реНрдкреНрд░рд╛рдкреНрддреАрд╕рд╛рдареА PITR рдХрд░реВ рд╢рдХрддреЛ: рдЕрдпрд╢рд╕реНрд╡реА рд╣реЛрдгреНрдпрд╛рдкреВрд░реНрд╡реА рдШреЗрддрд▓реЗрд▓реНрдпрд╛ рд╕реНрдиреЕрдкрд╢реЙрдЯрдкрд╛рд╕реВрди рд╕реБрд░реБрд╡рд╛рдд рдХрд░рдгреЗ рдЖрдгрд┐ WAL рд╕рдВрдЧреНрд░рд╣рдгрд╛рддреАрд▓ рдмрджрд▓ рдЕрдпрд╢рд╕реНрд╡реА рд╣реЛрдИрдкрд░реНрдпрдВрдд рд▓рд╛рдЧреВ рдХрд░рдгреЗ.

рд╕реНрдердЧрд┐рдд рдкреНрд░рддрд┐рдХреГрддреА рдореНрд╣рдгрдЬреЗ рдХрд╛рдп?

рдЖрд│рд╢реА рдкреНрд░рддрд┐рдХреГрддреА рдореНрд╣рдгрдЬреЗ WAL рдХрдбреВрди рд╡рд┐рд▓рдВрдмрд╛рдиреЗ рдХреЗрд▓реЗрд▓реЗ рдмрджрд▓. рдореНрд╣рдгрдЬреЗрдЪ рддрд╛рд╕рд╛рднрд░рд╛рдд рд╡реНрдпрд╡рд╣рд╛рд░ рдЭрд╛рд▓рд╛ X, рдкрд░рдВрддреБ рддреЗ рд╡рд┐рд▓рдВрдмрд╛рдиреЗ рдкреНрд░рддрд┐рдХреГрддреАрдордзреНрдпреЗ рджрд┐рд╕реВрди рдпреЗрдИрд▓ d рддрд╛рд╕рд╛рдд X + d.

рдкреЛрд╕реНрдЯрдЧреНрд░реЗрдПрд╕рдХреНрдпреВрдПрд▓рдХрдбреЗ рднреМрддрд┐рдХ рдбреЗрдЯрд╛рдмреЗрд╕ рдкреНрд░рддрд┐рдХреГрддреА рд╕реЗрдЯ рдХрд░рдгреНрдпрд╛рдЪреЗ 2 рдорд╛рд░реНрдЧ рдЖрд╣реЗрдд: рдмреЕрдХрдЕрдк рдкреБрдирд░реНрдкреНрд░рд╛рдкреНрддреА рдЖрдгрд┐ рдкреНрд░рд╡рд╛рд╣ рдкреНрд░рддрд┐рдХреГрддреА. рд╕рдВрдЧреНрд░рд╣рдгрд╛рддреВрди рдкреБрдирд░реНрд╕рдВрдЪрдпрд┐рдд рдХрд░рдд рдЖрд╣реЗ, рдореВрд▓рдд: PITR рдкреНрд░рдорд╛рдгреЗ рдХрд╛рд░реНрдп рдХрд░рддреЗ, рдкрд░рдВрддреБ рд╕рддрдд: рдЖрдореНрд╣реА рд╕рддрдд WAL рд╕рдВрдЧреНрд░рд╣рдгрд╛рддреВрди рдмрджрд▓ рдкреБрдирд░реНрдкреНрд░рд╛рдкреНрдд рдХрд░рддреЛ рдЖрдгрд┐ рддреЗ рдкреНрд░рддрд┐рдХреГрддреАрд╡рд░ рд▓рд╛рдЧреВ рдХрд░рддреЛ. рдП рдкреНрд░рд╡рд╛рд╣ рдкреНрд░рддрд┐рдХреГрддреА рдЕрдкрд╕реНрдЯреНрд░реАрдо рдбреЗрдЯрд╛рдмреЗрд╕ рд╣реЛрд╕реНрдЯрдордзреВрди рдереЗрдЯ WAL рдкреНрд░рд╡рд╛рд╣ рдкреБрдирд░реНрдкреНрд░рд╛рдкреНрдд рдХрд░рддреЛ. рдЖрдореНрд╣реА рд╕рдВрдЧреНрд░рд╣рдг рдкреБрдирд░реНрдкреНрд░рд╛рдкреНрддреАрд▓рд╛ рдкреНрд░рд╛рдзрд╛рдиреНрдп рджреЗрддреЛ - рддреЗ рд╡реНрдпрд╡рд╕реНрдерд╛рдкрд┐рдд рдХрд░рдгреЗ рд╕реЛрдкреЗ рдЖрд╣реЗ рдЖрдгрд┐ рд╕рд╛рдорд╛рдиреНрдп рдХрд╛рд░реНрдпрдкреНрд░рджрд░реНрд╢рди рдЖрд╣реЗ рдЬреЗ рдЙрддреНрдкрд╛рджрди рдХреНрд▓рд╕реНрдЯрд░рд╕рд╣ рд░рд╛рд╣рддреЗ.

рд╕рдВрдЧреНрд░рд╣рдгрд╛рддреВрди рд╡рд┐рд▓рдВрдмрд┐рдд рдкреБрдирд░реНрдкреНрд░рд╛рдкреНрддреА рдХрд╢реА рд╕реЗрдЯ рдХрд░рд╛рд╡реА

рдкреБрдирд░реНрдкреНрд░рд╛рдкреНрддреА рдкрд░реНрдпрд╛рдп рдлрд╛рдЗрд▓рдордзреНрдпреЗ рд╡рд░реНрдгрди рдХреЗрд▓реЗ рдЖрд╣реЗ recovery.conf. рдЙрджрд╛рд╣рд░рдгрдГ

standby_mode = 'on'
restore_command = '/usr/bin/envdir /etc/wal-e.d/env /opt/wal-e/bin/wal-e wal-fetch -p 4 "%f" "%p"'
recovery_min_apply_delay = '8h'
recovery_target_timeline = 'latest'

рдпрд╛ рдкреЕрд░рд╛рдореАрдЯрд░реНрд╕рд╕рд╣, рдЖрдореНрд╣реА рдмреЕрдХрдЕрдк рдкреБрдирд░реНрдкреНрд░рд╛рдкреНрддреАрд╕рд╣ рдПрдХ рд╕реНрдердЧрд┐рдд рдкреНрд░рддрд┐рдХреГрддреА рдХреЙрдиреНрдлрд┐рдЧрд░ рдХреЗрд▓реА рдЖрд╣реЗ. рдпреЗрдереЗ рддреЗ рд╡рд╛рдкрд░рд▓реЗ рдЬрд╛рддреЗ wal-e WAL рд╡рд┐рднрд╛рдЧ рдХрд╛рдврдгреНрдпрд╛рд╕рд╛рдареА (restore_command) рд╕рдВрдЧреНрд░рд╣рдгрд╛рддреВрди, рдЖрдгрд┐ рдмрджрд▓ рдЖрда рддрд╛рд╕рд╛рдВрдирдВрддрд░ рд▓рд╛рдЧреВ рдХреЗрд▓реЗ рдЬрд╛рддреАрд▓ (recovery_min_apply_delay). рдкреНрд░рддрд┐рдХреГрддреА рд╕рдВрдЧреНрд░рд╣рдгрд╛рддреАрд▓ рдЯрд╛рдЗрдорд▓рд╛рдЗрди рдмрджрд▓рд╛рдВрд╡рд░ рд▓рдХреНрд╖ рдареЗрд╡реЗрд▓, рдЙрджрд╛рд╣рд░рдгрд╛рд░реНрде рдХреНрд▓рд╕реНрдЯрд░ рдлреЗрд▓рдУрд╡реНрд╣рд░рдореБрд│реЗ (recovery_target_timeline).

╨б recovery_min_apply_delay рддреБрдореНрд╣реА рд╡рд┐рд▓рдВрдмрд╛рдиреЗ рд╕реНрдЯреНрд░реАрдорд┐рдВрдЧ рдкреНрд░рддрд┐рдХреГрддреА рд╕реЗрдЯ рдХрд░реВ рд╢рдХрддрд╛, рдкрд░рдВрддреБ рдпреЗрдереЗ рдХрд╛рд╣реА рддреЛрдЯреЗ рдЖрд╣реЗрдд рдЬреЗ рдкреНрд░рддрд┐рдХреГрддреА рд╕реНрд▓реЙрдЯ, рд╣реЙрдЯ рд╕реНрдЯрдБрдбрдмрд╛рдп рдлреАрдбрдмреЕрдХ рдЗрддреНрдпрд╛рджреАрдВрд╢реА рд╕рдВрдмрдВрдзрд┐рдд рдЖрд╣реЗрдд. WAL рд╕рдВрдЧреНрд░рд╣рдг рддреБрдореНрд╣рд╛рд▓рд╛ рддреЗ рдЯрд╛рд│рдгреНрдпрд╛рдЪреА рдкрд░рд╡рд╛рдирдЧреА рджреЗрддреЛ.

рдкреЕрд░рд╛рдореАрдЯрд░ recovery_min_apply_delay рдлрдХреНрдд PostgreSQL 9.3 рдордзреНрдпреЗ рджрд┐рд╕реВ рд▓рд╛рдЧрд▓реЗ. рдорд╛рдЧреАрд▓ рдЖрд╡реГрддреНрддреНрдпрд╛рдВрдордзреНрдпреЗ, рд╕реНрдердЧрд┐рдд рдкреНрд░рддрд┐рдХреГрддреАрд╕рд╛рдареА рдЖрдкрд▓реНрдпрд╛рд▓рд╛ рд╕рдВрдпреЛрдЬрди рдХреЙрдиреНрдлрд┐рдЧрд░ рдХрд░рдгреЗ рдЖрд╡рд╢реНрдпрдХ рдЖрд╣реЗ рдкреБрдирд░реНрдкреНрд░рд╛рдкреНрддреА рд╡реНрдпрд╡рд╕реНрдерд╛рдкрди рдХрд╛рд░реНрдпреЗ (pg_xlog_replay_pause(), pg_xlog_replay_resume()) рдХрд┐рдВрд╡рд╛ рд╡рд┐рд▓рдВрдмрд╛рдЪреНрдпрд╛ рдХрд╛рд▓рд╛рд╡рдзреАрд╕рд╛рдареА рд╕рдВрдЧреНрд░рд╣рдгрд╛рдд WAL рд╡рд┐рднрд╛рдЧ рдзрд░реВрди рдареЗрд╡рд╛.

PostgreSQL рд╣реЗ рдХрд╕реЗ рдХрд░рддреЗ?

PostgreSQL рдЖрд│рд╢реА рдкреБрдирд░реНрдкреНрд░рд╛рдкреНрддреА рдХрд╢реА рд▓рд╛рдЧреВ рдХрд░рддреЗ рд╣реЗ рдкрд╛рд╣рдгреЗ рдордиреЛрд░рдВрдЬрдХ рдЖрд╣реЗ. рдмрдШреВрдпрд╛ recoveryApplyDelay(XlogReaderState). рдкрд╛рд╕реВрди рдореНрд╣рдгрддрд╛рдд рдореБрдЦреНрдп рдкреБрдирд░рд╛рд╡реГрддреНрддреА рд▓реВрдк WAL рдХрдбреВрди рдкреНрд░рддреНрдпреЗрдХ рдкреНрд░рд╡реЗрд╢рд╛рд╕рд╛рдареА.

static bool
recoveryApplyDelay(XLogReaderState *record)
{
    uint8       xact_info;
    TimestampTz xtime;
    long        secs;
    int         microsecs;

    /* nothing to do if no delay configured */
    if (recovery_min_apply_delay <= 0)
        return false;

    /* no delay is applied on a database not yet consistent */
    if (!reachedConsistency)
        return false;

    /*
     * Is it a COMMIT record?
     *
     * We deliberately choose not to delay aborts since they have no effect on
     * MVCC. We already allow replay of records that don't have a timestamp,
     * so there is already opportunity for issues caused by early conflicts on
     * standbys.
     */
    if (XLogRecGetRmid(record) != RM_XACT_ID)
        return false;

    xact_info = XLogRecGetInfo(record) & XLOG_XACT_OPMASK;

    if (xact_info != XLOG_XACT_COMMIT &&
        xact_info != XLOG_XACT_COMMIT_PREPARED)
        return false;

    if (!getRecordTimestamp(record, &xtime))
        return false;

    recoveryDelayUntilTime =
        TimestampTzPlusMilliseconds(xtime, recovery_min_apply_delay);

    /*
     * Exit without arming the latch if it's already past time to apply this
     * record
     */
    TimestampDifference(GetCurrentTimestamp(), recoveryDelayUntilTime,
                        &secs, &microsecs);
    if (secs <= 0 && microsecs <= 0)
        return false;

    while (true)
    {
        // Shortened:
        // Use WaitLatch until we reached recoveryDelayUntilTime
        // and then
        break;
    }
    return true;
}

рдореБрдЦреНрдп рдЧреЛрд╖реНрдЯ рдЕрд╢реА рдЖрд╣реЗ рдХреА рд╡рд┐рд▓рдВрдм рд╣рд╛ рд╡реНрдпрд╡рд╣рд╛рд░ рдХрдорд┐рдЯ рдЯрд╛рдЗрдорд╕реНрдЯреЕрдореНрдкрдордзреНрдпреЗ рдиреЛрдВрджрд╡рд▓реЗрд▓реНрдпрд╛ рднреМрддрд┐рдХ рд╡реЗрд│реЗрд╡рд░ рдЖрдзрд╛рд░рд┐рдд рдЖрд╣реЗ (xtime). рддреБрдореНрд╣реА рдмрдШреВ рд╢рдХрддрд╛, рд╡рд┐рд▓рдВрдм рдлрдХреНрдд рдХрдорд┐рдЯрд▓рд╛ рд▓рд╛рдЧреВ рд╣реЛрддреЛ рдЖрдгрд┐ рдЗрддрд░ рдиреЛрдВрджреАрдВрд╡рд░ рдкрд░рд┐рдгрд╛рдо рдХрд░рдд рдирд╛рд╣реА - рд╕рд░реНрд╡ рдмрджрд▓ рдереЗрдЯ рд▓рд╛рдЧреВ рдХреЗрд▓реЗ рдЬрд╛рддрд╛рдд рдЖрдгрд┐ рдХрдорд┐рдЯрд▓рд╛ рдЙрд╢реАрд░ рд╣реЛрддреЛ, рддреНрдпрд╛рдореБрд│реЗ рдЖрдореНрд╣реА рдХреЙрдиреНрдлрд┐рдЧрд░ рдХреЗрд▓реЗрд▓реНрдпрд╛ рд╡рд┐рд▓рдВрдмрд╛рдирдВрддрд░рдЪ рдмрджрд▓ рдкрд╛рд╣реВ рд╢рдХрддреЛ.

рдбреЗрдЯрд╛ рдкреБрдирд░реНрд╕рдВрдЪрдпрд┐рдд рдХрд░рдгреНрдпрд╛рд╕рд╛рдареА рд╡рд┐рд▓рдВрдмрд┐рдд рдкреНрд░рддрд┐рдХреГрддреА рдХрд╢реА рд╡рд╛рдкрд░рд╛рд╡реА

рд╕рдордЬрд╛ рдЖрдордЪреНрдпрд╛рдХрдбреЗ рдбреЗрдЯрд╛рдмреЗрд╕ рдХреНрд▓рд╕реНрдЯрд░ рдЖрд╣реЗ рдЖрдгрд┐ рдЙрддреНрдкрд╛рджрдирд╛рдд рдЖрда рддрд╛рд╕рд╛рдВрдЪрд╛ рд╡рд┐рд▓рдВрдм рдЕрд╕рд▓реЗрд▓реА рдкреНрд░рддрд┐рдХреГрддреА рдЖрд╣реЗ. рдЪрд▓рд╛ рдПрдХ рдЙрджрд╛рд╣рд░рдг рд╡рд╛рдкрд░реВрди рдбреЗрдЯрд╛ рдХрд╕рд╛ рдкреБрдирд░реНрдкреНрд░рд╛рдкреНрдд рдХрд░рд╛рдпрдЪрд╛ рддреЗ рдкрд╛рд╣реВ рдЪреБрдХреВрди рд╢реЙрд░реНрдЯрдХрдЯ рд╣рдЯрд╡рдгреЗ.

рдЬреЗрд╡реНрд╣рд╛ рдЖрдореНрд╣рд╛рд▓рд╛ рд╕рдорд╕реНрдпреЗрдмрджреНрджрд▓ рдХрд│рд▓реЗ, рддреЗрд╡реНрд╣рд╛ рдЖрдореНрд╣реА рд╕рдВрдЧреНрд░рд╣рдг рдкреБрдирд░реНрд╕рдВрдЪрдпрд┐рдд рдХрд░рдгреНрдпрд╛рд╕ рд╡рд┐рд░рд╛рдо рджрд┐рд▓рд╛ рдЧреЗрд▓рд╛ рдЖрд╣реЗ рд╕реНрдердЧрд┐рдд рдкреНрд░рддрд┐рдХреГрддреАрд╕рд╛рдареА:

SELECT pg_xlog_replay_pause();

рд╡рд┐рд░рд╛рдо рджреЗрдКрди, рдкреНрд░рддрд┐рдХреГрддреА рд╡рд┐рдирдВрддреАрдЪреА рдкреБрдирд░рд╛рд╡реГрддреНрддреА рдХрд░реЗрд▓ рдпрд╛рдЪрд╛ рдЖрдореНрд╣рд╛рд▓рд╛ рдХреЛрдгрддрд╛рд╣реА рдзреЛрдХрд╛ рдирд╡реНрд╣рддрд╛ DELETE. рдЖрдкрд▓реНрдпрд╛рд▓рд╛ рд╕рд░реНрд╡рдХрд╛рд╣реА рд╢реЛрдзрдгреНрдпрд╛рд╕рд╛рдареА рд╡реЗрд│ рд╣рд╡рд╛ рдЕрд╕рд▓реНрдпрд╛рд╕ рдПрдХ рдЙрдкрдпреБрдХреНрдд рдЧреЛрд╖реНрдЯ.

рдореБрджреНрджрд╛ рдЕрд╕рд╛ рдЖрд╣реЗ рдХреА рд╕реНрдердЧрд┐рдд рдкреНрд░рддрд┐рдХреГрддреА рд╡рд┐рдирдВрддреАрдЪреНрдпрд╛ рдЖрдзреАрдЪреНрдпрд╛ рдХреНрд╖рдгреА рдкреЛрд╣реЛрдЪрд▓реА рдкрд╛рд╣рд┐рдЬреЗ DELETE. рдЖрдореНрд╣рд╛рд▓рд╛ рдХрд╛рдврдгреНрдпрд╛рдЪреА рднреМрддрд┐рдХ рд╡реЗрд│ рдЕрдВрджрд╛рдЬреЗ рдорд╛рд╣рд┐рдд рд╣реЛрддреА. рдЖрдореНрд╣реА рд╣рдЯрд╡рд▓реЗ рдЖрд╣реЗ recovery_min_apply_delay рдЖрдгрд┐ рдЬреЛрдбрд▓реЗ recovery_target_time ╨▓ recovery.conf. рд╡рд┐рд▓рдВрдм рди рдХрд░рддрд╛ рдкреНрд░рддрд┐рдХреГрддреА рдпреЛрдЧреНрдп рдХреНрд╖рдгреА рдЕрд╢рд╛ рдкреНрд░рдХрд╛рд░реЗ рдкреЛрд╣реЛрдЪрддреЗ:

recovery_target_time = '2018-10-12 09:25:00+00'

рдЯрд╛рдЗрдо рд╕реНрдЯреЕрдореНрдкрд╕рд╣, рдЪреБрдХреВ рдирдпреЗ рдореНрд╣рдгреВрди рдЬрд╛рджрд╛ рдХрдореА рдХрд░рдгреЗ рдЪрд╛рдВрдЧрд▓реЗ рдЖрд╣реЗ. рдЦрд░реЗ рдЖрд╣реЗ, рдЬрд┐рддрдХреЗ рдЬрд╛рд╕реНрдд рдХрдореА рд╣реЛрдИрд▓ рддрд┐рддрдХрд╛ рдбреЗрдЯрд╛ рдЖрдкрдг рдЧрдорд╛рд╡рддреЛ. рдкреБрдиреНрд╣рд╛, рдЖрдореНрд╣реА рд╡рд┐рдирдВрддреА рдЪреБрдХрд▓реНрдпрд╛рд╕ DELETE, рд╕рд░реНрд╡рдХрд╛рд╣реА рдкреБрдиреНрд╣рд╛ рд╣рдЯрд╡рд▓реЗ рдЬрд╛рдИрд▓ рдЖрдгрд┐ рддреБрдореНрд╣рд╛рд▓рд╛ рдкреБрдиреНрд╣рд╛ рд╕реБрд░реБрд╡рд╛рдд рдХрд░рд╛рд╡реА рд▓рд╛рдЧреЗрд▓ (рдХрд┐рдВрд╡рд╛ PITR рд╕рд╛рдареА рдХреЛрд▓реНрдб рдмреЕрдХрдЕрдк рджреЗрдЦреАрд▓ рдШреНрдпрд╛рд╡рд╛ рд▓рд╛рдЧреЗрд▓).

рдЖрдореНрд╣реА рд╕реНрдердЧрд┐рдд рдкреЛрд╕реНрдЯрдЧреНрд░реЗрд╕ рдЙрджрд╛рд╣рд░рдг рд░реАрд╕реНрдЯрд╛рд░реНрдЯ рдХреЗрд▓реЗ рдЖрдгрд┐ рдирд┐рд░реНрджрд┐рд╖реНрдЯ рд╡реЗрд│реЗрдкрд░реНрдпрдВрдд WAL рд╡рд┐рднрд╛рдЧрд╛рдВрдЪреА рдкреБрдирд░рд╛рд╡реГрддреНрддреА рдХреЗрд▓реА рдЧреЗрд▓реА. рддреБрдореНрд╣реА рд╡рд┐рдЪрд╛рд░реВрди рдпрд╛ рдЯрдкреНрдкреНрдпрд╛рд╡рд░ рдкреНрд░рдЧрддреАрдЪрд╛ рдорд╛рдЧреЛрд╡рд╛ рдШреЗрдК рд╢рдХрддрд╛:

SELECT
  -- current location in WAL
  pg_last_xlog_replay_location(),
  -- current transaction timestamp (state of the replica)
  pg_last_xact_replay_timestamp(),
  -- current physical time
  now(),
  -- the amount of time still to be applied until recovery_target_time has been reached
  '2018-10-12 09:25:00+00'::timestamptz - pg_last_xact_replay_timestamp() as delay;

рдЯрд╛рдЗрдорд╕реНрдЯреЕрдореНрдк рдпрд╛рдкреБрдвреЗ рдмрджрд▓рдд рдирд╕рд▓реНрдпрд╛рд╕, рдкреБрдирд░реНрдкреНрд░рд╛рдкреНрддреА рдкреВрд░реНрдг рд╣реЛрдИрд▓. рдХреГрддреА рд╕рд╛рдиреБрдХреВрд▓рд┐рдд рдХреЗрд▓реА рдЬрд╛рдК рд╢рдХрддреЗ recovery_target_actionрдкреБрдиреНтАНрд╣рд╛ рдкреНрд░рдпрддреНтАНрди рдХреЗрд▓реНтАНрдпрд╛рдирдВрддрд░ рдШрдЯрдирд╛ рдмрдВрдж рдХрд░рдгреЗ, рдкреНрд░рдЪрд╛рд░ рдХрд░рдгреЗ рдХрд┐рдВрд╡рд╛ рд╡рд┐рд░рд╛рдо рджреЗрдгреЗ (рддреЗ рдбреАрдлреЙрд▓реНрдЯрдиреБрд╕рд╛рд░ рдирд┐рд▓рдВрдмрд┐рдд рдХреЗрд▓реЗ рдЬрд╛рддреЗ).

рддреНрдпрд╛ рджреБрд░реНрджреИрд╡реА рд╡рд┐рдирдВрддреАрдкреВрд░реНрд╡реА рдбреЗрдЯрд╛рдмреЗрд╕ рддреНрдпрд╛рдЪреНрдпрд╛ рд╕реНрдерд┐рддреАрдд рдкрд░рдд рдЖрд▓рд╛. рдЖрддрд╛ рдЖрдкрдг, рдЙрджрд╛рд╣рд░рдгрд╛рд░реНрде, рдбреЗрдЯрд╛ рдирд┐рд░реНрдпрд╛рдд рдХрд░реВ рд╢рдХрддрд╛. рдЖрдореНрд╣реА рд╣рдЯрд╡рд▓реЗрд▓рд╛ рд▓реЗрдмрд▓ рдбреЗрдЯрд╛ рдЖрдгрд┐ рд╕рдорд╕реНрдпрд╛рдВрдЪреЗ рд╕рд░реНрд╡ рджреБрд╡реЗ рдирд┐рд░реНрдпрд╛рдд рдХреЗрд▓реЗ рдЖрдгрд┐ рд╡рд┐рдирдВрддреНрдпрд╛ рдПрдХрддреНрд░ рдХреЗрд▓реНрдпрд╛ рдЖрдгрд┐ рддреНрдпрд╛рдВрдирд╛ рдЙрддреНрдкрд╛рджрди рдбреЗрдЯрд╛рдмреЗрд╕рдордзреНрдпреЗ рд╣рд▓рд╡рд▓реЗ. рдиреБрдХрд╕рд╛рди рдореЛрдареНрдпрд╛ рдкреНрд░рдорд╛рдгрд╛рдд рдЕрд╕рд▓реНрдпрд╛рд╕, рддреБрдореНрд╣реА рдлрдХреНрдд рдкреНрд░рддрд┐рдХреГрддреАрд▓рд╛ рдкреНрд░реЛрддреНрд╕рд╛рд╣рди рджреЗрдК рд╢рдХрддрд╛ рдЖрдгрд┐ рдореБрдЦреНрдп рдореНрд╣рдгреВрди рд╡рд╛рдкрд░реВ рд╢рдХрддрд╛. рдкрд░рдВрддреБ рдирдВрддрд░ рдЖрдкрдг рдЬреНрдпрд╛ рдмрд┐рдВрджреВрдкрд░реНрдпрдВрдд рдкреБрдирд░реНрдкреНрд░рд╛рдкреНрдд рдЭрд╛рд▓реЛ рдЖрд╣реЛрдд рддреНрдпрд╛ рдирдВрддрд░рдЪреЗ рд╕рд░реНрд╡ рдмрджрд▓ рдЧрдорд╛рд╡рд▓реЗ рдЬрд╛рддреАрд▓.

рдЯрд╛рдЗрдорд╕реНрдЯреЕрдореНрдкрдРрд╡рдЬреА, рд╡реНрдпрд╡рд╣рд╛рд░ рдЖрдпрдбреА рд╡рд╛рдкрд░рдгреЗ рдЪрд╛рдВрдЧрд▓реЗ. рд╣реЗ рдЖрдпрдбреА рд░реЗрдХреЙрд░реНрдб рдХрд░рдгреЗ рдЙрдкрдпреБрдХреНрдд рдЖрд╣реЗ, рдЙрджрд╛рд╣рд░рдгрд╛рд░реНрде, рдбреАрдбреАрдПрд▓ рд╕реНрдЯреЗрдЯрдореЗрдВрдЯрд╕рд╛рдареА (рдЬрд╕реЗ рдХреА DROP TABLE), рд╡рд╛рдкрд░реВрди log_statements = 'ddl'. рдЖрдордЪреНрдпрд╛рдХрдбреЗ рдЯреНрд░рд╛рдиреНрдЭреЕрдХреНрд╢рди рдЖрдпрдбреА рдЕрд╕реЗрд▓ рддрд░ рдЖрдореНрд╣реА рдШреЗрдК recovery_target_xid рдЖрдгрд┐ рд╡рд┐рдирдВрддреА рдХрд░рдгреНрдпрд╛рдкреВрд░реНрд╡реА рд╡реНрдпрд╡рд╣рд╛рд░рд╛рдкрд░реНрдпрдВрдд рд╕рд░реНрд╡ рдХрд╛рд╣реА рдХреЗрд▓реЗ DELETE.

рдХрд╛рдорд╛рд╡рд░ рдкрд░рдд рдЬрд╛рдгреЗ рдЦреВрдк рд╕реЛрдкреЗ рдЖрд╣реЗ: рд╕рд░реНрд╡ рдмрджрд▓ рдХрд╛рдвреВрди рдЯрд╛рдХрд╛ recovery.conf рдЖрдгрд┐ рдкреЛрд╕реНрдЯрдЧреНрд░реЗрд╕ рд░реАрд╕реНрдЯрд╛рд░реНрдЯ рдХрд░рд╛. рдкреНрд░рддрд┐рдХреГрддреАрд▓рд╛ рд▓рд╡рдХрд░рдЪ рдкреБрдиреНрд╣рд╛ рдЖрда рддрд╛рд╕рд╛рдВрдЪрд╛ рд╡рд┐рд▓рдВрдм рд╣реЛрдИрд▓ рдЖрдгрд┐ рдЖрдореНрд╣реА рднрд╡рд┐рд╖реНрдпрд╛рддреАрд▓ рддреНрд░рд╛рд╕рд╛рдВрд╕рд╛рдареА рддрдпрд╛рд░ рдЖрд╣реЛрдд.

рдкреБрдирд░реНрдкреНрд░рд╛рдкреНрддреА рдлрд╛рдпрджреЗ

рдХреЛрд▓реНрдб рдмреЕрдХрдЕрдкрдРрд╡рдЬреА рд╕реНрдердЧрд┐рдд рдкреНрд░рддрд┐рдХреГрддреАрд╕рд╣, рдЖрдкрд▓реНрдпрд╛рд▓рд╛ рд╕рдВрдЧреНрд░рд╣рдгрд╛рддреВрди рд╕рдВрдкреВрд░реНрдг рдкреНрд░рддрд┐рдорд╛ рдкреБрдирд░реНрд╕рдВрдЪрдпрд┐рдд рдХрд░рдгреНрдпрд╛рд╕рд╛рдареА рдХрд╛рд╣реА рддрд╛рд╕ рдШрд╛рд▓рд╡рд╛рд╡реЗ рд▓рд╛рдЧрдгрд╛рд░ рдирд╛рд╣реАрдд. рдЙрджрд╛рд╣рд░рдгрд╛рд░реНрде, рд╕рдВрдкреВрд░реНрдг рдореВрд▓рднреВрдд 2 TB рдмреЕрдХрдЕрдк рдорд┐рд│рд╡рд┐рдгреНрдпрд╛рд╕рд╛рдареА рдЖрдореНрд╣рд╛рд▓рд╛ рдкрд╛рдЪ рддрд╛рд╕ рд▓рд╛рдЧрддрд╛рдд. рдЖрдгрд┐ рдордЧ рддреБрдореНрд╣рд╛рд▓рд╛ рдЕрдЬреВрдирд╣реА рдЗрдЪреНрдЫрд┐рдд рд╕реНрдерд┐рддреАрдд (рд╕рд░реНрд╡рд╛рдд рд╡рд╛рдИрдЯ рдкрд░рд┐рд╕реНрдерд┐рддреАрдд) рдкреБрдирд░реНрдкреНрд░рд╛рдкреНрдд рдХрд░рдгреНрдпрд╛рд╕рд╛рдареА рд╕рдВрдкреВрд░реНрдг рджреИрдирд┐рдХ WAL рд▓рд╛рдЧреВ рдХрд░рд╛рд╡реЗ рд▓рд╛рдЧреЗрд▓.

рдПрдХ рд╕реНрдердЧрд┐рдд рдкреНрд░рддрд┐рдХреГрддреА рджреЛрди рдкреНрд░рдХрд╛рд░реЗ рдХреЛрд▓реНрдб рдмреЕрдХрдЕрдкрдкреЗрдХреНрд╖рд╛ рдЪрд╛рдВрдЧрд▓реА рдЖрд╣реЗ:

  1. рд╕рдВрдЧреНрд░рд╣рдгрд╛рддреВрди рд╕рдВрдкреВрд░реНрдг рдореВрд▓рднреВрдд рдмреЕрдХрдЕрдк рдХрд╛рдврдгреНрдпрд╛рдЪреА рдЧрд░рдЬ рдирд╛рд╣реА.
  2. WAL рд╡рд┐рднрд╛рдЧрд╛рдВрдЪреА рдПрдХ рдирд┐рд╢реНрдЪрд┐рдд рдЖрда-рддрд╛рд╕ рд╡рд┐рдВрдбреЛ рдЖрд╣реЗ рдЬреА рдкреБрдирд░рд╛рд╡реГрддреНрддреА рдХрд░рдгреЗ рдЖрд╡рд╢реНрдпрдХ рдЖрд╣реЗ.

WAL рд╡рд░реВрди PITR рдмрдирд╡рдгреЗ рд╢рдХреНрдп рдЖрд╣реЗ рдХреА рдирд╛рд╣реА рд╣реЗ рджреЗрдЦреАрд▓ рдЖрдореНрд╣реА рд╕рддрдд рддрдкрд╛рд╕рдд рдЕрд╕рддреЛ рдЖрдгрд┐ рд╕реНрдердЧрд┐рдд рдкреНрд░рддрд┐рдХреГрддреАрдЪреНрдпрд╛ рдЕрдВрддрд░рд╛рд╡рд░ рд▓рдХреНрд╖ рдареЗрд╡реВрди WAL рд╕рдВрдЧреНрд░рд╣рдгрд╛рддреАрд▓ рднреНрд░рд╖реНрдЯрд╛рдЪрд╛рд░ рдХрд┐рдВрд╡рд╛ рдЗрддрд░ рд╕рдорд╕реНрдпрд╛ рдЖрдореНрд╣рд╛рд▓рд╛ рддреНрд╡рд░реАрдд рд▓рдХреНрд╖рд╛рдд рдпреЗрддреАрд▓.

рдпрд╛ рдЙрджрд╛рд╣рд░рдгрд╛рдд, рдЖрдореНрд╣рд╛рд▓рд╛ рдкреБрдирд░реНрд╕рдВрдЪрдпрд┐рдд рдХрд░рдгреНрдпрд╛рд╕рд╛рдареА 50 рдорд┐рдирд┐рдЯреЗ рд▓рд╛рдЧрд▓реА, рдпрд╛рдЪрд╛ рдЕрд░реНрде рд╡реЗрдЧ рдкреНрд░рддрд┐ рддрд╛рд╕ 110 GB WAL рдбреЗрдЯрд╛ рд╣реЛрддрд╛ (рд╕рдВрдЧреНрд░рд╣рдг рдЕрджреНрдпрд╛рдк рд╕реБрд░реВ рд╣реЛрддреЗ рдПрдбрдмреНрд▓реНрдпреВрдПрд╕ рдПрд╕ 3). рдПрдХреВрдг, рдЖрдореНрд╣реА рд╕рдорд╕реНрдпреЗрдЪреЗ рдирд┐рд░рд╛рдХрд░рдг рдХреЗрд▓реЗ рдЖрдгрд┐ 1,5 рддрд╛рд╕рд╛рдВрдордзреНрдпреЗ рдбреЗрдЯрд╛ рдкреБрдирд░реНрдкреНрд░рд╛рдкреНрдд рдХреЗрд▓рд╛.

рдкрд░рд┐рдгрд╛рдо: рдЬрд┐рдереЗ рд╕реНрдердЧрд┐рдд рдкреНрд░рддрд┐рдХреГрддреА рдЙрдкрдпреБрдХреНрдд рдЖрд╣реЗ (рдЖрдгрд┐ рдХреБрдареЗ рдирд╛рд╣реА)

рдЬрд░ рддреБрдореНрд╣реА рдЪреБрдХреВрди рдбреЗрдЯрд╛ рдЧрдорд╛рд╡рд▓рд╛ рдЖрдгрд┐ рдХреЙрдиреНрдлрд┐рдЧрд░ рдХреЗрд▓реЗрд▓реНрдпрд╛ рд╡рд┐рд▓рдВрдмрд╛рдордзреНрдпреЗ рд╣реА рд╕рдорд╕реНрдпрд╛ рд▓рдХреНрд╖рд╛рдд рдЖрд▓реА рддрд░ рдкреНрд░рдердореЛрдкрдЪрд╛рд░ рдореНрд╣рдгреВрди рд╡рд┐рд▓рдВрдмрд┐рдд рдкреНрд░рддрд┐рдХреГрддреА рд╡рд╛рдкрд░рд╛.

рдкрд░рдВрддреБ рд▓рдХреНрд╖рд╛рдд рдареЗрд╡рд╛: рдкреНрд░рддрд┐рдХреГрддреА рдмреЕрдХрдЕрдк рдирд╛рд╣реА.

рдмреЕрдХрдЕрдк рдЖрдгрд┐ рдкреНрд░рддрд┐рдХреГрддреАрдЪреЗ рд╡реЗрдЧрд╡реЗрдЧрд│реЗ рдЙрджреНрджреЗрд╢ рдЖрд╣реЗрдд. рддреБрдореНрд╣реА рдЪреБрдХреВрди рдмрдирд╡рд▓реНрдпрд╛рд╕ рдХреЛрд▓реНрдб рдмреЕрдХрдЕрдк рдЙрдкрдпреЛрдЧреА рдкрдбреЗрд▓ DELETE рдХрд┐рдВрд╡рд╛ DROP TABLE. рдЖрдореНрд╣реА рдХреЛрд▓реНрдб рд╕реНрдЯреЛрд░реЗрдЬрдордзреВрди рдмреЕрдХрдЕрдк рдмрдирд╡рддреЛ рдЖрдгрд┐ рдЯреЗрдмрд▓рдЪреА рдХрд┐рдВрд╡рд╛ рд╕рдВрдкреВрд░реНрдг рдбреЗрдЯрд╛рдмреЗрд╕рдЪреА рдорд╛рдЧреАрд▓ рд╕реНрдерд┐рддреА рдкреБрдирд░реНрд╕рдВрдЪрдпрд┐рдд рдХрд░рддреЛ. рдкрдг рддреНрдпрд╛рдЪ рд╡реЗрд│реА рд╡рд┐рдирдВрддреА DROP TABLE рдХрд╛рд░реНрдпрд░рдд рдХреНрд▓рд╕реНрдЯрд░рд╡рд░реАрд▓ рд╕рд░реНрд╡ рдкреНрд░рддрд┐рдХреГрддреАрдВрдордзреНрдпреЗ рдЬрд╡рд│рдЬрд╡рд│ рддреНрд╡рд░рд┐рдд рдкреБрдирд░реБрддреНрдкрд╛рджрд┐рдд рдХреЗрд▓реЗ рдЬрд╛рддреЗ, рдореНрд╣рдгреВрди рд╕рд╛рдорд╛рдиреНрдп рдкреНрд░рддрд┐рдХреГрддреА рдпреЗрдереЗ рдорджрдд рдХрд░рдгрд╛рд░ рдирд╛рд╣реА. рд╡реИрдпрдХреНрддрд┐рдХ рд╕рд░реНрд╡реНрд╣рд░ рдбрд╛рдЙрди рдЕрд╕рддрд╛рдирд╛ рдЖрдгрд┐ рд▓реЛрдбрдЪреЗ рд╡рд┐рддрд░рдг рдХрд░рддрд╛рдирд╛ рдкреНрд░рддрд┐рдХреГрддреА рд╕реНрд╡рддрдГ рдбреЗрдЯрд╛рдмреЗрд╕ рдЙрдкрд▓рдмреНрдз рдареЗрд╡рддреЗ.

рдЕрдЧрджреА рд▓рд╛рдВрдмрдгреАрд╡рд░ рдЯрд╛рдХрд▓реЗрд▓реНрдпрд╛ рдкреНрд░рддрд┐рдХреГрддреАрд╕рд╣, рдбреЗрдЯрд╛ рд╕реЗрдВрдЯрд░рдордзреНрдпреЗ рдмрд┐рдШрд╛рдб, рд▓рдкрд╡рд┐рд▓реЗрд▓реЗ рдиреБрдХрд╕рд╛рди рдХрд┐рдВрд╡рд╛ рд▓рдЧреЗрдЪ рд▓рдХреНрд╖рд╛рдд рди рдпреЗрдгрд╛рд░реНтАНрдпрд╛ рдШрдЯрдирд╛ рдШрдбрд▓реНрдпрд╛рд╕ рдЖрдореНрд╣рд╛рд▓рд╛ рдХрдзреАрдХрдзреА рд╕реБрд░рдХреНрд╖рд┐рдд рдард┐рдХрд╛рдгреА рдердВрдб рдмреЕрдХрдЕрдкрдЪреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдЕрд╕рддреЗ. рдпреЗрдереЗ рдХреЗрд╡рд│ рдкреНрд░рддрд┐рдХреГрддреАрдЪрд╛ рдЙрдкрдпреЛрдЧ рдирд╛рд╣реА.

рд╢реЗрд░рд╛. рдЪрд╛рд▓реВ GitLab.com рдЖрдореНрд╣реА рд╕рдзреНрдпрд╛ рдлрдХреНрдд рд╕рд┐рд╕реНрдЯрдо рд╕реНрддрд░рд╛рд╡рд░ рдбреЗрдЯрд╛ рдЧрдорд╛рд╡рдгреНрдпрд╛рдкрд╛рд╕реВрди рд╕рдВрд░рдХреНрд╖рдг рдХрд░рддреЛ рдЖрдгрд┐ рд╡рд╛рдкрд░рдХрд░реНрддрд╛ рд╕реНрддрд░рд╛рд╡рд░ рдбреЗрдЯрд╛ рдкреБрдирд░реНрдкреНрд░рд╛рдкреНрдд рдХрд░рдд рдирд╛рд╣реА.

рд╕реНрддреНрд░реЛрдд: www.habr.com

рдПрдХ рдЯрд┐рдкреНрдкрдгреА рдЬреЛрдбрд╛