Π Π΅ΠΏΠ»ΠΈΠΊΠ°ΡΠΈΡΡΠ° Π½Π΅ Π΅ ΡΠ΅Π·Π΅ΡΠ²Π½ΠΎ ΠΊΠΎΠΏΠΈΠ΅. ΠΠ»ΠΈ Π½Π΅? ΠΡΠΎ ΠΊΠ°ΠΊ ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°Ρ
ΠΌΠ΅ ΠΎΡΠ»ΠΎΠΆΠ΅Π½Π° ΡΠ΅ΠΏΠ»ΠΈΠΊΠ°ΡΠΈΡ Π·Π° Π²ΡΠ·ΡΡΠ°Π½ΠΎΠ²ΡΠ²Π°Π½Π΅ ΠΎΡ ΡΠ»ΡΡΠ°ΠΉΠ½ΠΎ ΠΈΠ·ΡΡΠΈΡΠΈ ΠΏΡΠ΅ΠΊΠΈ ΠΏΡΡΠΈΡΠ°.
Π Π΅ΠΏΠ»ΠΈΠΊΠ°ΡΠΈΡΡΠ° Π½Π΅ Π΅ ΡΡΠ΅Π΄ΡΡΠ²ΠΎ Π·Π° Π°ΡΡ
ΠΈΠ²ΠΈΡΠ°Π½Π΅ Π½Π° Π±Π°Π·ΠΈ Π΄Π°Π½Π½ΠΈ (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
ΠΠ°Π·Π°ΡΠ° Π΄Π°Π½Π½ΠΈ ΡΠ΅ Π²ΡΡΠ½Π° Π² ΡΡΡΡΠΎΡΠ½ΠΈΠ΅ΡΠΎ ΡΠΈ ΠΏΡΠ΅Π΄ΠΈ ΡΠ°Π·ΠΈ Π·Π»ΠΎΠΏΠΎΠ»ΡΡΠ½Π° Π·Π°ΡΠ²ΠΊΠ°. Π‘Π΅Π³Π° ΠΌΠΎΠΆΠ΅ΡΠ΅ Π½Π°ΠΏΡΠΈΠΌΠ΅Ρ Π΄Π° Π΅ΠΊΡΠΏΠΎΡΡΠΈΡΠ°ΡΠ΅ Π΄Π°Π½Π½ΠΈ. ΠΠΊΡΠΏΠΎΡΡΠΈΡΠ°Ρ ΠΌΠ΅ ΠΈΠ·ΡΡΠΈΡΠΈΡΠ΅ Π΄Π°Π½Π½ΠΈ Π·Π° Π΅ΡΠΈΠΊΠ΅ΡΠΈ ΠΈ Π²ΡΠΈΡΠΊΠΈ Π²ΡΡΠ·ΠΊΠΈ ΠΊΡΠΌ ΠΏΡΠΎΠ±Π»Π΅ΠΌΠΈ ΠΈ Π·Π°ΡΠ²ΠΊΠΈ Π·Π° ΡΠ»ΠΈΠ²Π°Π½Π΅ ΠΈ Π³ΠΈ ΠΏΡΠ΅ΠΌΠ΅ΡΡΠΈΡ ΠΌΠ΅ Π² ΠΏΡΠΎΠΈΠ·Π²ΠΎΠ΄ΡΡΠ²Π΅Π½Π°ΡΠ° Π±Π°Π·Π° Π΄Π°Π½Π½ΠΈ. ΠΠΊΠΎ Π·Π°Π³ΡΠ±ΠΈΡΠ΅ ΡΠ° Π³ΠΎΠ»Π΅ΠΌΠΈ, ΠΌΠΎΠΆΠ΅ΡΠ΅ ΠΏΡΠΎΡΡΠΎ Π΄Π° ΡΠ΅ΠΊΠ»Π°ΠΌΠΈΡΠ°ΡΠ΅ ΡΠ΅ΠΏΠ»ΠΈΠΊΠ°ΡΠ° ΠΈ Π΄Π° Ρ ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°ΡΠ΅ ΠΊΠ°ΡΠΎ ΠΎΡΠ½ΠΎΠ²Π½Π°. ΠΠΎ ΡΠΎΠ³Π°Π²Π° Π²ΡΠΈΡΠΊΠΈ ΠΏΡΠΎΠΌΠ΅Π½ΠΈ ΡΠ»Π΅Π΄ ΡΠΎΡΠΊΠ°ΡΠ°, Π΄ΠΎ ΠΊΠΎΡΡΠΎ ΡΠΌΠ΅ ΡΠ΅ Π²ΡΠ·ΡΡΠ°Π½ΠΎΠ²ΠΈΠ»ΠΈ, ΡΠ΅ Π±ΡΠ΄Π°Ρ Π·Π°Π³ΡΠ±Π΅Π½ΠΈ.
ΠΠΌΠ΅ΡΡΠΎ Π²ΡΠ΅ΠΌΠ΅Π²ΠΈ ΠΎΡΠΏΠ΅ΡΠ°ΡΡΡΠΈ Π΅ ΠΏΠΎ-Π΄ΠΎΠ±ΡΠ΅ Π΄Π° ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°ΡΠ΅ ΠΈΠ΄Π΅Π½ΡΠΈΡΠΈΠΊΠ°ΡΠΎΡΠΈ Π½Π° ΡΡΠ°Π½Π·Π°ΠΊΡΠΈΠΈ. ΠΠΎΠ»Π΅Π·Π½ΠΎ Π΅ Π΄Π° Π·Π°ΠΏΠΈΡΠ²Π°ΡΠ΅ ΡΠ΅Π·ΠΈ ΠΈΠ΄Π΅Π½ΡΠΈΡΠΈΠΊΠ°ΡΠΎΡΠΈ, Π½Π°ΠΏΡΠΈΠΌΠ΅Ρ, Π·Π° 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