Π Π΅ΠΏΠ»ΠΈΠΊΠ°ΡΠΈΡΠ°ΡΠ° Π½Π΅ Π΅ ΡΠ΅Π·Π΅ΡΠ²Π½Π° ΠΊΠΎΠΏΠΈΡΠ°. ΠΠ»ΠΈ Π½Π΅? ΠΠ²Π΅ ΠΊΠ°ΠΊΠΎ ΠΊΠΎΡΠΈΡΡΠ΅Π²ΠΌΠ΅ ΠΎΠ΄Π»ΠΎΠΆΠ΅Π½Π° ΡΠ΅ΠΏΠ»ΠΈΠΊΠ°ΡΠΈΡΠ° Π·Π° Π΄Π° ΡΠ΅ ΠΎΠΏΠΎΡΠ°Π²ΠΈΠΌΠ΅ ΠΎΠ΄ ΡΠ»ΡΡΠ°ΡΠ½ΠΎ Π±ΡΠΈΡΠ΅ΡΠ΅ ΠΊΡΠ°ΡΠ΅Π½ΠΊΠΈ.
Π Π΅ΠΏΠ»ΠΈΠΊΠ°ΡΠΈΡΠ°ΡΠ° Π½Π΅ Π΅ ΡΡΠ΅Π΄ΡΡΠ²ΠΎ Π·Π° ΡΠ΅Π·Π΅ΡΠ²Π½Π° ΠΊΠΎΠΏΠΈΡΠ° Π½Π° Π±Π°Π·ΠΈΡΠ΅ Π½Π° ΠΏΠΎΠ΄Π°ΡΠΎΡΠΈ (gitlab-ce
Π‘ΠΎ ΠΎΠ΄Π»ΠΎΠΆΠ΅Π½Π° ΡΠ΅ΠΏΠ»ΠΈΠΊΠ°, Π³ΠΈ Π²ΡΠ°ΡΠΈΠ²ΠΌΠ΅ ΠΏΠΎΠ΄Π°ΡΠΎΡΠΈΡΠ΅ Π·Π° ΡΠ°ΠΌΠΎ 1,5 ΡΠ°ΡΠ°. ΠΠΎΠ³Π»Π΅Π΄Π½Π΅ΡΠ΅ ΠΊΠ°ΠΊΠΎ ΡΠ΅ ΡΠ»ΡΡΠΈ.
ΠΠ°Π²Π΅Π΄Π΅ΡΠ΅ Π³ΠΎ Π²ΡΠ΅ΠΌΠ΅ΡΠΎ Π·Π° ΠΎΠ±Π½ΠΎΠ²ΡΠ²Π°ΡΠ΅ ΡΠΎ PostgreSQL
PostgreSQL ΠΈΠΌΠ° Π²Π³ΡΠ°Π΄Π΅Π½Π° ΡΡΠ½ΠΊΡΠΈΡΠ° ΠΊΠΎΡΠ° ΡΠ° Π²ΡΠ°ΡΠ° ΡΠΎΡΡΠΎΡΠ±Π°ΡΠ° Π½Π° Π±Π°Π·Π°ΡΠ° Π½Π° ΠΏΠΎΠ΄Π°ΡΠΎΡΠΈ Π΄ΠΎ ΠΎΠ΄ΡΠ΅Π΄Π΅Π½Π° Π²ΡΠ΅ΠΌΠ΅Π½ΡΠΊΠ° ΡΠΎΡΠΊΠ°. Π’ΠΎΠ° ΡΠ΅ Π½Π°ΡΠ΅ΠΊΡΠ²Π°
ΠΠ° Π΄Π° ΡΠ° ΠΊΠΎΡΠΈΡΡΠΈΠΌΠ΅ ΠΎΠ²Π°Π° ΡΡΠ½ΠΊΡΠΈΡΠ° Π·Π° Π»Π°Π΄Π½Π° ΡΠ΅Π·Π΅ΡΠ²Π½Π° ΠΊΠΎΠΏΠΈΡΠ°, Π½ΠΈΠ΅ ΡΠ΅Π΄ΠΎΠ²Π½ΠΎ ΠΏΡΠ°Π²ΠΈΠΌΠ΅ ΠΎΡΠ½ΠΎΠ²Π½Π° ΡΠ΅Π·Π΅ΡΠ²Π½Π° ΠΊΠΎΠΏΠΈΡΠ° Π½Π° Π±Π°Π·Π°ΡΠ° Π½Π° ΠΏΠΎΠ΄Π°ΡΠΎΡΠΈ ΠΈ ΡΠ° ΡΠΊΠ»Π°Π΄ΠΈΡΠ°ΠΌΠ΅ Π²ΠΎ Π°ΡΡ
ΠΈΠ²Π° (Π°ΡΡ
ΠΈΠ²ΠΈΡΠ΅ Π½Π° GitLab ΠΆΠΈΠ²Π΅Π°Ρ Π²ΠΎ
Π¨ΡΠΎ Π΅ ΠΎΠ΄Π»ΠΎΠΆΠ΅Π½Π° ΡΠ΅ΠΏΠ»ΠΈΠΊΠ°ΡΠΈΡΠ°?
ΠΡΠ·Π»ΠΈΠ²Π° ΡΠ΅ΠΏΠ»ΠΈΠΊΠ°ΡΠΈΡΠ° Π΅ ΠΏΡΠΈΠΌΠ΅Π½Π° Π½Π° ΠΏΡΠΎΠΌΠ΅Π½ΠΈ ΠΎΠ΄ WAL ΡΠΎ Π·Π°Π΄ΠΎΡΠ½ΡΠ²Π°ΡΠ΅. Π’ΠΎΠ° Π΅, ΡΡΠ°Π½ΡΠ°ΠΊΡΠΈΡΠ°ΡΠ° ΡΠ΅ ΡΠ»ΡΡΠΈ Π·Π° Π΅Π΄Π΅Π½ ΡΠ°Ρ X
, Π½ΠΎ ΡΠ΅ ΡΠ΅ ΠΏΠΎΡΠ°Π²ΠΈ Π²ΠΎ ΡΠ΅ΠΏΠ»ΠΈΠΊΠ°ΡΠ° ΡΠΎ Π·Π°Π΄ΠΎΡΠ½ΡΠ²Π°ΡΠ΅ d
Π·Π° Π΅Π΄Π΅Π½ ΡΠ°Ρ X + d
.
PostgreSQL ΠΈΠΌΠ° 2 Π½Π°ΡΠΈΠ½ΠΈ Π·Π° ΠΏΠΎΡΡΠ°Π²ΡΠ²Π°ΡΠ΅ Π½Π° ΡΠ΅ΠΏΠ»ΠΈΠΊΠ° Π½Π° ΡΠΈΠ·ΠΈΡΠΊΠ° Π±Π°Π·Π° Π½Π° ΠΏΠΎΠ΄Π°ΡΠΎΡΠΈ: Π²ΡΠ°ΡΠ°ΡΠ΅ Π½Π° ΡΠ΅Π·Π΅ΡΠ²Π½Π°ΡΠ° ΠΊΠΎΠΏΠΈΡΠ° ΠΈ ΡΠ΅ΠΏΠ»ΠΈΠΊΠ°ΡΠΈΡΠ° Π½Π° ΡΡΡΠΈΠΌΠΈΠ½Π³.
ΠΠ°ΠΊΠΎ Π΄Π° ΠΏΠΎΡΡΠ°Π²ΠΈΡΠ΅ ΠΎΠ΄Π»ΠΎΠΆΠ΅Π½ΠΎ ΠΎΠ±Π½ΠΎΠ²ΡΠ²Π°ΡΠ΅ ΠΎΠ΄ Π°ΡΡ ΠΈΠ²Π°
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'
Π‘ΠΎ ΠΎΠ²ΠΈΠ΅ ΠΏΠ°ΡΠ°ΠΌΠ΅ΡΡΠΈ, ΠΊΠΎΠ½ΡΠΈΠ³ΡΡΠΈΡΠ°Π²ΠΌΠ΅ ΠΎΠ΄Π»ΠΎΠΆΠ΅Π½Π° ΡΠ΅ΠΏΠ»ΠΈΠΊΠ° ΡΠΎ Π²ΡΠ°ΡΠ°ΡΠ΅ Π½Π° ΡΠ΅Π·Π΅ΡΠ²Π½Π°ΡΠ° ΠΊΠΎΠΏΠΈΡΠ°. Π’ΡΠΊΠ° ΡΠ΅ ΠΊΠΎΡΠΈΡΡΠΈ 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)
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, µsecs);
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).
ΠΠΎ ΡΠ΅ΡΡΠ°ΡΡΠΈΡΠ°Π²ΠΌΠ΅ ΠΎΠ΄Π»ΠΎΠΆΠ΅Π½ΠΈΠΎΡ ΠΏΡΠΈΠΌΠ΅ΡΠΎΠΊ Π½Π° Postgres ΠΈ ΡΠ΅Π³ΠΌΠ΅Π½ΡΠΈΡΠ΅ 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
ΠΠ°Π·Π°ΡΠ° Π½Π° ΠΏΠΎΠ΄Π°ΡΠΎΡΠΈ ΡΠ΅ Π²ΡΠ°ΡΠΈ Π²ΠΎ ΡΠ²ΠΎΡΠ°ΡΠ° ΡΠΎΡΡΠΎΡΠ±Π° ΠΏΡΠ΅Π΄ ΡΠΎΠ° Π½Π΅ΡΡΠ΅ΡΠ½ΠΎ Π±Π°ΡΠ°ΡΠ΅. Π‘Π΅Π³Π° ΠΌΠΎΠΆΠ΅ΡΠ΅, Π½Π° ΠΏΡΠΈΠΌΠ΅Ρ, Π΄Π° ΠΈΠ·Π²Π΅Π·ΡΠ²Π°ΡΠ΅ ΠΏΠΎΠ΄Π°ΡΠΎΡΠΈ. ΠΠΈ ΠΈΠ·Π²Π΅Π·ΠΎΠ²ΠΌΠ΅ ΠΈΠ·Π±ΡΠΈΡΠ°Π½ΠΈΡΠ΅ ΠΏΠΎΠ΄Π°ΡΠΎΡΠΈ Π·Π° Π΅ΡΠΈΠΊΠ΅ΡΠ°ΡΠ° ΠΈ ΡΠΈΡΠ΅ Π²ΡΡΠΊΠΈ Π΄ΠΎ ΠΏΡΠΎΠ±Π»Π΅ΠΌΠΈ ΠΈ Π±Π°ΡΠ°ΡΠ° Π·Π° ΡΠΏΠΎΡΡΠ²Π°ΡΠ΅ ΠΈ Π³ΠΈ ΠΏΡΠ΅ΠΌΠ΅ΡΡΠΈΠ²ΠΌΠ΅ Π²ΠΎ Π±Π°Π·Π°ΡΠ° Π½Π° ΠΏΠΎΠ΄Π°ΡΠΎΡΠΈ Π·Π° ΠΏΡΠΎΠΈΠ·Π²ΠΎΠ΄ΡΡΠ²ΠΎ. ΠΠΊΠΎ Π·Π°Π³ΡΠ±ΠΈΡΠ΅ ΡΠ΅ Π³ΠΎΠ»Π΅ΠΌΠΈ, ΠΌΠΎΠΆΠ΅ΡΠ΅ Π΅Π΄Π½ΠΎΡΡΠ°Π²Π½ΠΎ Π΄Π° ΡΠ° ΠΏΡΠΎΠΌΠΎΠ²ΠΈΡΠ°ΡΠ΅ ΡΠ΅ΠΏΠ»ΠΈΠΊΠ°ΡΠ° ΠΈ Π΄Π° ΡΠ° ΠΊΠΎΡΠΈΡΡΠΈΡΠ΅ ΠΊΠ°ΠΊΠΎ Π³Π»Π°Π²Π½Π°. ΠΠΎ, ΡΠΎΠ³Π°Ρ ΡΠΈΡΠ΅ ΠΏΡΠΎΠΌΠ΅Π½ΠΈ ΠΏΠΎ ΡΠΎΡΠΊΠ°ΡΠ° Π΄ΠΎ ΠΊΠΎΡΠ° ΡΠ΅ ΠΎΠΏΠΎΡΠ°Π²ΠΈΠ²ΠΌΠ΅ ΡΠ΅ Π±ΠΈΠ΄Π°Ρ ΠΈΠ·Π³ΡΠ±Π΅Π½ΠΈ.
ΠΠ°ΠΌΠ΅ΡΡΠΎ Π²ΡΠ΅ΠΌΠ΅Π½ΡΠΊΠΈ ΠΏΠ΅ΡΠ°ΡΠΈ, ΠΏΠΎΠ΄ΠΎΠ±ΡΠΎ Π΅ Π΄Π° ΠΊΠΎΡΠΈΡΡΠΈΡΠ΅ ID Π½Π° ΡΡΠ°Π½ΡΠ°ΠΊΡΠΈΠΈ. ΠΠΎΡΠΈΡΠ½ΠΎ Π΅ Π΄Π° ΡΠ΅ ΡΠ½ΠΈΠΌΠ°Π°Ρ ΠΎΠ²ΠΈΠ΅ ID, Π½Π° ΠΏΡΠΈΠΌΠ΅Ρ, Π·Π° DDL ΠΈΠ·ΡΠ°Π²ΠΈ (ΠΊΠ°ΠΊΠΎ Π½Π° ΠΏΡ DROP TABLE
), ΡΠΎ ΠΊΠΎΡΠΈΡΡΠ΅ΡΠ΅ Π½Π° log_statements = 'ddl'
. ΠΠ° ΠΈΠΌΠ°Π²ΠΌΠ΅ Π»ΠΈΡΠ½Π° ΠΊΠ°ΡΡΠ° Π·Π° ΡΡΠ°Π½ΡΠ°ΠΊΡΠΈΡΠ°, ΡΠ΅ Π·Π΅ΠΌΠ΅Π²ΠΌΠ΅ recovery_target_xid
ΠΈ ΠΈΡΡΡΡΠ° ΡΓ¨ Π΄ΠΎ ΡΡΠ°Π½ΡΠ°ΠΊΡΠΈΡΠ°ΡΠ° ΠΏΡΠ΅Π΄ Π±Π°ΡΠ°ΡΠ΅ΡΠΎ DELETE
.
ΠΡΠ°ΡΠ°ΡΠ΅ΡΠΎ Π½Π° ΡΠ°Π±ΠΎΡΠ° Π΅ ΠΌΠ½ΠΎΠ³Ρ Π΅Π΄Π½ΠΎΡΡΠ°Π²Π½ΠΎ: ΠΎΡΡΡΡΠ°Π½Π΅ΡΠ΅ Π³ΠΈ ΡΠΈΡΠ΅ ΠΏΡΠΎΠΌΠ΅Π½ΠΈ ΠΎΠ΄ recovery.conf
ΠΈ ΡΠ΅ΡΡΠ°ΡΡΠΈΡΠ°ΡΡΠ΅ Π³ΠΎ Postgres. Π Π΅ΠΏΠ»ΠΈΠΊΠ°ΡΠ° Π½Π°ΡΠΊΠΎΡΠΎ ΡΠ΅ ΠΈΠΌΠ° ΠΏΠΎΠ²ΡΠΎΡΠ½ΠΎ Π΄ΠΎΡΠ½Π΅ΡΠ΅ ΠΎΠ΄ ΠΎΡΡΠΌ ΡΠ°ΡΠ°, Π° Π½ΠΈΠ΅ ΡΠΌΠ΅ ΠΏΠΎΠ΄Π³ΠΎΡΠ²Π΅Π½ΠΈ Π·Π° ΠΈΠ΄Π½ΠΈ Π½Π΅Π²ΠΎΠ»ΡΠΈ.
ΠΡΠΈΠ΄ΠΎΠ±ΠΈΠ²ΠΊΠΈ Π·Π° Π·Π°ΠΊΡΠ΅ΠΏΠ½ΡΠ²Π°ΡΠ΅
Π‘ΠΎ ΠΎΠ΄Π»ΠΎΠΆΠ΅Π½Π° ΡΠ΅ΠΏΠ»ΠΈΠΊΠ° Π½Π°ΠΌΠ΅ΡΡΠΎ Π»Π°Π΄Π½Π° ΡΠ΅Π·Π΅ΡΠ²Π½Π° ΠΊΠΎΠΏΠΈΡΠ°, Π½Π΅ ΠΌΠΎΡΠ° Π΄Π° ΡΡΠΎΡΠΈΡΠ΅ ΡΠ°ΡΠΎΠ²ΠΈ Π·Π° Π΄Π° ΡΠ° Π²ΡΠ°ΡΠΈΡΠ΅ ΡΠ΅Π»Π°ΡΠ° ΡΠ»ΠΈΠΊΠ° ΠΎΠ΄ Π°ΡΡ ΠΈΠ²Π°ΡΠ°. ΠΠ° ΠΏΡΠΈΠΌΠ΅Ρ, Π½ΠΈ ΡΡΠ΅Π±Π°Π°Ρ ΠΏΠ΅Ρ ΡΠ°ΡΠ° Π·Π° Π΄Π° ΡΠ° Π΄ΠΎΠ±ΠΈΠ΅ΠΌΠ΅ ΡΠ΅Π»Π°ΡΠ° ΠΎΡΠ½ΠΎΠ²Π½Π° ΡΠ΅Π·Π΅ΡΠ²Π½Π° ΠΊΠΎΠΏΠΈΡΠ° ΠΎΠ΄ 2 TB. Π ΡΠΎΠ³Π°Ρ ΡΓ¨ ΡΡΡΠ΅ ΡΡΠ΅Π±Π° Π΄Π° Π³ΠΎ ΠΏΡΠΈΠΌΠ΅Π½ΠΈΡΠ΅ ΡΠ΅Π»ΠΈΠΎΡ Π΄Π½Π΅Π²Π΅Π½ WAL Π·Π° Π΄Π° ΡΠ΅ Π²ΡΠ°ΡΠΈΡΠ΅ Π²ΠΎ ΠΏΠΎΡΠ°ΠΊΡΠ²Π°Π½Π°ΡΠ° ΡΠΎΡΡΠΎΡΠ±Π° (Π²ΠΎ Π½Π°ΡΠ»ΠΎΡ ΡΠ»ΡΡΠ°Ρ).
ΠΠ΄Π»ΠΎΠΆΠ΅Π½Π°ΡΠ° ΡΠ΅ΠΏΠ»ΠΈΠΊΠ° Π΅ ΠΏΠΎΠ΄ΠΎΠ±ΡΠ° ΠΎΠ΄ Π»Π°Π΄Π½Π° ΡΠ΅Π·Π΅ΡΠ²Π½Π° ΠΊΠΎΠΏΠΈΡΠ° Π½Π° Π΄Π²Π° Π½Π°ΡΠΈΠ½Π°:
- ΠΠ΅ΠΌΠ° ΠΏΠΎΡΡΠ΅Π±Π° Π΄Π° ΡΠ΅ ΠΎΡΡΡΡΠ°Π½ΠΈ ΡΠ΅Π»Π°ΡΠ° ΠΎΡΠ½ΠΎΠ²Π½Π° ΡΠ΅Π·Π΅ΡΠ²Π½Π° ΠΊΠΎΠΏΠΈΡΠ° ΠΎΠ΄ Π°ΡΡ ΠΈΠ²Π°ΡΠ°.
- ΠΠΌΠ° ΡΠΈΠΊΡΠ΅Π½ ΠΎΡΡΠΌΡΠ°ΡΠΎΠ²Π΅Π½ ΠΏΡΠΎΠ·ΠΎΡΠ΅Ρ Π½Π° WAL ΡΠ΅Π³ΠΌΠ΅Π½ΡΠΈ ΠΊΠΎΡ ΠΌΠΎΡΠ° Π΄Π° ΡΠ΅ ΠΏΠΎΠ²ΡΠΎΡΠΈ.
ΠΡΡΠΎ ΡΠ°ΠΊΠ°, ΠΏΠΎΡΡΠΎΡΠ°Π½ΠΎ ΠΏΡΠΎΠ²Π΅ΡΡΠ²Π°ΠΌΠ΅ Π΄Π°Π»ΠΈ Π΅ ΠΌΠΎΠΆΠ½ΠΎ Π΄Π° ΡΠ΅ Π½Π°ΠΏΡΠ°Π²ΠΈ PITR ΠΎΠ΄ WAL ΠΈ Π±ΡΠ·ΠΎ Π±ΠΈ Π·Π°Π±Π΅Π»Π΅ΠΆΠ°Π»Π΅ ΠΊΠΎΡΡΠΏΡΠΈΡΠ° ΠΈΠ»ΠΈ Π΄ΡΡΠ³ΠΈ ΠΏΡΠΎΠ±Π»Π΅ΠΌΠΈ ΡΠΎ Π°ΡΡ ΠΈΠ²Π°ΡΠ° Π½Π° WAL ΡΠΎ ΡΠ»Π΅Π΄Π΅ΡΠ΅ Π½Π° Π·Π°Π΄ΠΎΡΠ½ΡΠ²Π°ΡΠ΅ΡΠΎ Π½Π° ΠΎΠ΄Π»ΠΎΠΆΠ΅Π½Π°ΡΠ° ΡΠ΅ΠΏΠ»ΠΈΠΊΠ°.
ΠΠΎ ΠΎΠ²ΠΎΡ ΠΏΡΠΈΠΌΠ΅Ρ, Π½ΠΈ ΡΡΠ΅Π±Π°Π° 50 ΠΌΠΈΠ½ΡΡΠΈ Π·Π° Π²ΡΠ°ΡΠ°ΡΠ΅, ΡΡΠΎ Π·Π½Π°ΡΠΈ Π΄Π΅ΠΊΠ° Π±ΡΠ·ΠΈΠ½Π°ΡΠ° Π±Π΅ΡΠ΅ 110 GB WAL ΠΏΠΎΠ΄Π°ΡΠΎΡΠΈ Π½Π° ΡΠ°Ρ (Π°ΡΡ
ΠΈΠ²Π°ΡΠ° ΡΓ¨ ΡΡΡΠ΅ Π±Π΅ΡΠ΅ Π²ΠΊΠ»ΡΡΠ΅Π½Π°
Π Π΅Π·ΡΠ»ΡΠ°ΡΠΈ: ΠΊΠ°Π΄Π΅ Π΅ ΠΊΠΎΡΠΈΡΠ½Π° ΠΎΠ΄Π»ΠΎΠΆΠ΅Π½Π°ΡΠ° ΡΠ΅ΠΏΠ»ΠΈΠΊΠ° (Π° ΠΊΠ°Π΄Π΅ Π½Π΅ Π΅)
ΠΠΎΡΠΈΡΡΠ΅ΡΠ΅ Π·Π°Π΄ΠΎΡΠ½Π΅ΡΠ° ΡΠ΅ΠΏΠ»ΠΈΠΊΠ°ΡΠΈΡΠ° ΠΊΠ°ΠΊΠΎ ΠΏΡΠ²Π° ΠΏΠΎΠΌΠΎΡ Π°ΠΊΠΎ ΡΠ»ΡΡΠ°ΡΠ½ΠΎ ΡΡΠ΅ ΠΈΠ·Π³ΡΠ±ΠΈΠ»Π΅ ΠΏΠΎΠ΄Π°ΡΠΎΡΠΈ ΠΈ ΡΡΠ΅ Π³ΠΎ Π·Π°Π±Π΅Π»Π΅ΠΆΠ°Π»Π΅ ΠΎΠ²ΠΎΡ ΠΏΡΠΎΠ±Π»Π΅ΠΌ Π²ΠΎ ΡΠ°ΠΌΠΊΠΈΡΠ΅ Π½Π° ΠΊΠΎΠ½ΡΠΈΠ³ΡΡΠΈΡΠ°Π½ΠΎΡΠΎ Π΄ΠΎΡΠ½Π΅ΡΠ΅.
ΠΠΎ, ΠΈΠΌΠ°ΡΡΠ΅ Π½Π° ΡΠΌ: ΡΠ΅ΠΏΠ»ΠΈΠΊΠ°ΡΠΈΡΠ°ΡΠ° Π½Π΅ Π΅ ΡΠ΅Π·Π΅ΡΠ²Π½Π° ΠΊΠΎΠΏΠΈΡΠ°.
Π Π΅Π·Π΅ΡΠ²Π½Π°ΡΠ° ΠΊΠΎΠΏΠΈΡΠ° ΠΈ ΡΠ΅ΠΏΠ»ΠΈΠΊΠ°ΡΠΈΡΠ°ΡΠ° ΠΈΠΌΠ°Π°Ρ ΡΠ°Π·Π»ΠΈΡΠ½ΠΈ ΡΠ΅Π»ΠΈ. ΠΠ°Π΄Π½Π° ΡΠ΅Π·Π΅ΡΠ²Π½Π° ΠΊΠΎΠΏΠΈΡΠ° ΡΠ΅ Π²ΠΈ ΠΏΠΎΠΌΠΎΠ³Π½Π΅ Π°ΠΊΠΎ ΡΠ»ΡΡΠ°ΡΠ½ΠΎ ΡΡΠ΅ ΡΠ° Π½Π°ΠΏΡΠ°Π²ΠΈΠ»Π΅ DELETE
ΠΈΠ»ΠΈ DROP TABLE
. ΠΡΠ°Π²ΠΈΠΌΠ΅ ΡΠ΅Π·Π΅ΡΠ²Π½Π° ΠΊΠΎΠΏΠΈΡΠ° ΠΎΠ΄ Π»Π°Π΄ΠΈΠ»Π½ΠΈΠΊΠΎΡ ΠΈ ΡΠ° Π²ΡΠ°ΡΠ°ΠΌΠ΅ ΠΏΡΠ΅ΡΡ
ΠΎΠ΄Π½Π°ΡΠ° ΡΠΎΡΡΠΎΡΠ±Π° Π½Π° ΡΠ°Π±Π΅Π»Π°ΡΠ° ΠΈΠ»ΠΈ ΡΠ΅Π»Π°ΡΠ° Π±Π°Π·Π° Π½Π° ΠΏΠΎΠ΄Π°ΡΠΎΡΠΈ. ΠΠΎ Π²ΠΎ ΠΈΡΡΠΎ Π²ΡΠ΅ΠΌΠ΅ ΠΈ Π±Π°ΡΠ°ΡΠ΅ΡΠΎ DROP TABLE
Π Π΅ΡΠΈΡΠΈ Π²Π΅Π΄Π½Π°Ρ ΡΠ΅ ΡΠ΅ΠΏΡΠΎΠ΄ΡΡΠΈΡΠ° Π²ΠΎ ΡΠΈΡΠ΅ ΡΠ΅ΠΏΠ»ΠΈΠΊΠΈ Π½Π° ΡΠ°Π±ΠΎΡΠ½ΠΈΠΎΡ ΠΊΠ»Π°ΡΡΠ΅Ρ, ΡΠ°ΠΊΠ° ΡΡΠΎ ΠΎΠ±ΠΈΡΠ½Π°ΡΠ° ΡΠ΅ΠΏΠ»ΠΈΠΊΠ°ΡΠΈΡΠ° Π½Π΅ΠΌΠ° Π΄Π° ΠΏΠΎΠΌΠΎΠ³Π½Π΅ ΠΎΠ²Π΄Π΅. Π‘Π°ΠΌΠ°ΡΠ° ΡΠ΅ΠΏΠ»ΠΈΠΊΠ°ΡΠΈΡΠ° ΡΠ° ΠΎΠ΄ΡΠΆΡΠ²Π° Π±Π°Π·Π°ΡΠ° Π½Π° ΠΏΠΎΠ΄Π°ΡΠΎΡΠΈ Π΄ΠΎΡΡΠ°ΠΏΠ½Π° ΠΊΠΎΠ³Π° ΡΠ΅ ΠΈΠ·Π΄Π°Π²Π°Π°Ρ ΠΏΠΎΠ΅Π΄ΠΈΠ½Π΅ΡΠ½ΠΈ ΡΠ΅ΡΠ²Π΅ΡΠΈ ΠΈ Π³ΠΎ Π΄ΠΈΡΡΡΠΈΠ±ΡΠΈΡΠ° ΡΠΎΠ²Π°ΡΠΎΡ.
ΠΡΡΠΈ ΠΈ ΡΠΎ ΠΎΠ΄Π»ΠΎΠΆΠ΅Π½Π° ΡΠ΅ΠΏΠ»ΠΈΠΊΠ°, ΠΏΠΎΠ½Π΅ΠΊΠΎΠ³Π°Ρ Π½Π°Π²ΠΈΡΡΠΈΠ½Π° Π½ΠΈ ΡΡΠ΅Π±Π° Π»Π°Π΄Π½Π° ΡΠ΅Π·Π΅ΡΠ²Π½Π° ΠΊΠΎΠΏΠΈΡΠ° Π½Π° Π±Π΅Π·Π±Π΅Π΄Π½ΠΎ ΠΌΠ΅ΡΡΠΎ Π°ΠΊΠΎ ΡΠ΅ ΠΏΠΎΡΠ°Π²ΠΈ Π΄Π΅ΡΠ΅ΠΊΡ Π½Π° ΡΠ΅Π½ΡΠ°ΡΠΎΡ Π·Π° ΠΏΠΎΠ΄Π°ΡΠΎΡΠΈ, ΡΠΊΡΠΈΠ΅Π½ΠΎ ΠΎΡΡΠ΅ΡΡΠ²Π°ΡΠ΅ ΠΈΠ»ΠΈ Π΄ΡΡΠ³ΠΈ Π½Π°ΡΡΠ°Π½ΠΈ ΡΡΠΎ Π½Π΅ ΡΠ΅ Π²Π΅Π΄Π½Π°Ρ Π·Π°Π±Π΅Π»Π΅ΠΆΠ»ΠΈΠ²ΠΈ. Π‘Π°ΠΌΠΎ ΡΠ΅ΠΏΠ»ΠΈΠΊΠ°ΡΠΈΡΠ°ΡΠ° Π½Π΅ΠΌΠ° Π½ΠΈΠΊΠ°ΠΊΠ²Π° ΠΊΠΎΡΠΈΡΡ ΠΎΠ²Π΄Π΅.
ΠΠΌΠ°ΡΡΠ΅ Π½Π° ΡΠΌ. ΠΠ°
ΠΠ·Π²ΠΎΡ: www.habr.com