Π Π΅ΠΏΠ»ΠΈΠΊΠ°ΡΠΈΡ β Π½Π΅ Π±ΡΠΊΠ°ΠΏ. ΠΠ»ΠΈ Π½Π΅Ρ? ΠΠΎΡ ΠΊΠ°ΠΊ ΠΌΡ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°Π»ΠΈ ΠΎΡΠ»ΠΎΠΆΠ΅Π½Π½ΡΡ ΡΠ΅ΠΏΠ»ΠΈΠΊΠ°ΡΠΈΡ Π΄Π»Ρ Π²ΠΎΡΡΡΠ°Π½ΠΎΠ²Π»Π΅Π½ΠΈΡ, ΡΠ»ΡΡΠ°ΠΉΠ½ΠΎ ΡΠ΄Π°Π»ΠΈΠ² ΡΡΠ»ΡΠΊΠΈ.
Π Π΅ΠΏΠ»ΠΈΠΊΠ°ΡΠΈΡ β ΡΡΠΎ Π²Π°ΠΌ Π½Π΅ ΡΡΠ΅Π΄ΡΡΠ²ΠΎ Π±ΡΠΊΠ°ΠΏΠ° Π±Π°Π· Π΄Π°Π½Π½ΡΡ
(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'
. ΠΡΠ΄Ρ Ρ Π½Π°Ρ ID ΡΡΠ°Π½Π·Π°ΠΊΡΠΈΠΈ, ΠΌΡ Π±Ρ Π²Π·ΡΠ»ΠΈ recovery_target_xid
ΠΈ ΠΏΡΠΎΠ³Π½Π°Π»ΠΈ Π²ΡΠ΅ Π²ΠΏΠ»ΠΎΡΡ Π΄ΠΎ ΡΡΠ°Π½Π·Π°ΠΊΡΠΈΠΈ ΠΏΠ΅ΡΠ΅Π΄ Π·Π°ΠΏΡΠΎΡΠΎΠΌ DELETE
.
ΠΠ΅ΡΠ½ΡΡΡΡΡ ΠΊ ΡΠ°Π±ΠΎΡΠ΅ ΠΎΡΠ΅Π½Ρ ΠΏΡΠΎΡΡΠΎ: ΡΠ±Π΅ΡΠΈΡΠ΅ Π²ΡΠ΅ ΠΈΠ·ΠΌΠ΅Π½Π΅Π½ΠΈΡ ΠΈΠ· recovery.conf
ΠΈ ΠΏΠ΅ΡΠ΅Π·Π°ΠΏΡΡΡΠΈΡΠ΅ Postgres. Π‘ΠΊΠΎΡΠΎ Π² ΡΠ΅ΠΏΠ»ΠΈΠΊΠ΅ ΡΠ½ΠΎΠ²Π° ΠΏΠΎΡΠ²ΠΈΡΡΡ Π²ΠΎΡΡΠΌΠΈΡΠ°ΡΠΎΠ²Π°Ρ Π·Π°Π΄Π΅ΡΠΆΠΊΠ°, ΠΈ ΠΌΡ Π³ΠΎΡΠΎΠ²Ρ ΠΊ Π±ΡΠ΄ΡΡΠΈΠΌ Π½Π΅ΠΏΡΠΈΡΡΠ½ΠΎΡΡΡΠΌ.
ΠΡΠ΅ΠΈΠΌΡΡΠ΅ΡΡΠ²Π° Π΄Π»Ρ Π²ΠΎΡΡΡΠ°Π½ΠΎΠ²Π»Π΅Π½ΠΈΡ
Π‘ ΠΎΡΠ»ΠΎΠΆΠ΅Π½Π½ΠΎΠΉ ΡΠ΅ΠΏΠ»ΠΈΠΊΠΎΠΉ Π²ΠΌΠ΅ΡΡΠΎ Ρ ΠΎΠ»ΠΎΠ΄Π½ΠΎΠ³ΠΎ Π±ΡΠΊΠ°ΠΏΠ° Π½Π΅ ΠΏΡΠΈΡ ΠΎΠ΄ΠΈΡΡΡ ΡΠ°ΡΠ°ΠΌΠΈ Π²ΠΎΡΡΡΠ°Π½Π°Π²Π»ΠΈΠ²Π°ΡΡ Π²Π΅ΡΡ ΡΠ½ΠΈΠΌΠΎΠΊ ΠΈΠ· Π°ΡΡ ΠΈΠ²Π°. ΠΠ°ΠΌ, Π½Π°ΠΏΡΠΈΠΌΠ΅Ρ, Π½ΡΠΆΠ½ΠΎ ΠΏΡΡΡ ΡΠ°ΡΠΎΠ², ΡΡΠΎΠ±Ρ Π΄ΠΎΡΡΠ°ΡΡ Π²Π΅ΡΡ Π±Π°Π·ΠΎΠ²ΡΠΉ Π±ΡΠΊΠ°ΠΏ Π½Π° 2 Π’Π. Π ΠΏΠΎΡΠΎΠΌ Π΅ΡΠ΅ ΠΏΡΠΈΠ΄Π΅ΡΡΡ ΠΏΡΠΈΠΌΠ΅Π½ΠΈΡΡ Π²Π΅ΡΡ ΡΡΡΠΎΡΠ½ΡΠΉ WAL, ΡΡΠΎΠ±Ρ Π²ΠΎΡΡΡΠ°Π½ΠΎΠ²ΠΈΡΡΡΡ Π΄ΠΎ Π½ΡΠΆΠ½ΠΎΠ³ΠΎ ΡΠΎΡΡΠΎΡΠ½ΠΈΡ (Π² Ρ ΡΠ΄ΡΠ΅ΠΌ ΡΠ»ΡΡΠ°Π΅).
ΠΡΠ»ΠΎΠΆΠ΅Π½Π½Π°Ρ ΡΠ΅ΠΏΠ»ΠΈΠΊΠ° Π»ΡΡΡΠ΅ Ρ ΠΎΠ»ΠΎΠ΄Π½ΠΎΠ³ΠΎ Π±ΡΠΊΠ°ΠΏΠ° ΠΏΠΎ Π΄Π²ΡΠΌ ΠΏΡΠ½ΠΊΡΠ°ΠΌ:
- ΠΠ΅ Π½ΡΠΆΠ½ΠΎ Π΄ΠΎΡΡΠ°Π²Π°ΡΡ Π²Π΅ΡΡ Π±Π°Π·ΠΎΠ²ΡΠΉ Π±ΡΠΊΠ°ΠΏ ΠΈΠ· Π°ΡΡ ΠΈΠ²Π°.
- ΠΡΡΡ ΡΠΈΠΊΡΠΈΡΠΎΠ²Π°Π½Π½ΠΎΠ΅ Π²ΠΎΡΡΠΌΠΈΡΠ°ΡΠΎΠ²ΠΎΠ΅ ΠΎΠΊΠ½ΠΎ ΡΠ΅Π³ΠΌΠ΅Π½ΡΠΎΠ² WAL, ΠΊΠΎΡΠΎΡΡΠ΅ Π½ΡΠΆΠ½ΠΎ ΠΏΠΎΠ²ΡΠΎΡΠΈΡΡ.
Π Π΅ΡΠ΅ ΠΌΡ ΠΏΠΎΡΡΠΎΡΠ½Π½ΠΎ ΠΏΡΠΎΠ²Π΅ΡΡΠ΅ΠΌ, ΠΌΠΎΠΆΠ½ΠΎ Π»ΠΈ ΡΠ΄Π΅Π»Π°ΡΡ PITR ΠΈΠ· WAL, ΠΈ ΠΌΡ Π±Ρ Π±ΡΡΡΡΠΎ Π·Π°ΠΌΠ΅ΡΠΈΠ»ΠΈ ΠΏΠΎΠ²ΡΠ΅ΠΆΠ΄Π΅Π½ΠΈΡ ΠΈΠ»ΠΈ Π΄ΡΡΠ³ΠΈΠ΅ ΠΏΡΠΎΠ±Π»Π΅ΠΌΡ Ρ Π°ΡΡ ΠΈΠ²ΠΎΠΌ WAL, ΡΠ»Π΅Π΄Ρ Π·Π° ΠΎΡΡΡΠ°Π²Π°Π½ΠΈΠ΅ΠΌ ΠΎΡΠ»ΠΎΠΆΠ΅Π½Π½ΠΎΠΉ ΡΠ΅ΠΏΠ»ΠΈΠΊΠΈ.
Π ΡΡΠΎΠΌ ΠΏΡΠΈΠΌΠ΅ΡΠ΅ Ρ Π½Π°Ρ ΡΡΠ»ΠΎ 50 ΠΌΠΈΠ½ΡΡ Π½Π° Π²ΠΎΡΡΡΠ°Π½ΠΎΠ²Π»Π΅Π½ΠΈΠ΅, ΡΠΎ Π΅ΡΡΡ ΡΠΊΠΎΡΠΎΡΡΡ Π±ΡΠ»Π° 110 ΠΠ Π΄Π°Π½Π½ΡΡ
WAL Π² ΡΠ°Ρ (Π°ΡΡ
ΠΈΠ² ΡΠΎΠ³Π΄Π° Π²ΡΠ΅ Π΅ΡΠ΅ Π±ΡΠ» Π½Π°
ΠΡΠΎΠ³ΠΈ: Π³Π΄Π΅ ΠΏΡΠΈΠ³ΠΎΠ΄ΠΈΡΡΡ ΠΎΡΠ»ΠΎΠΆΠ΅Π½Π½Π°Ρ ΡΠ΅ΠΏΠ»ΠΈΠΊΠ° (Π° Π³Π΄Π΅ Π½Π΅Ρ)
ΠΡΠΏΠΎΠ»ΡΠ·ΡΠΉΡΠ΅ ΠΎΡΠ»ΠΎΠΆΠ΅Π½Π½ΡΡ ΡΠ΅ΠΏΠ»ΠΈΠΊΠ°ΡΠΈΡ ΠΊΠ°ΠΊ ΡΡΠ΅Π΄ΡΡΠ²ΠΎ ΠΏΠ΅ΡΠ²ΠΎΠΉ ΠΏΠΎΠΌΠΎΡΠΈ, Π΅ΡΠ»ΠΈ ΡΠ»ΡΡΠ°ΠΉΠ½ΠΎ ΠΏΠΎΡΠ΅ΡΡΠ»ΠΈ Π΄Π°Π½Π½ΡΠ΅ ΠΈ Π·Π°ΠΌΠ΅ΡΠΈΠ»ΠΈ ΡΡΡ Π±Π΅Π΄Ρ Π² ΠΏΡΠ΅Π΄Π΅Π»Π°Ρ Π½Π°ΡΡΡΠΎΠ΅Π½Π½ΠΎΠΉ Π·Π°Π΄Π΅ΡΠΆΠΊΠΈ.
ΠΠΎ ΡΡΡΠΈΡΠ΅: ΡΠ΅ΠΏΠ»ΠΈΠΊΠ°ΡΠΈΡ β Π½Π΅ Π±ΡΠΊΠ°ΠΏ.
Π£ Π±ΡΠΊΠ°ΠΏΠ° ΠΈ ΡΠ΅ΠΏΠ»ΠΈΠΊΠ°ΡΠΈΠΈ ΡΠ°Π·Π½ΡΠ΅ ΡΠ΅Π»ΠΈ. Π₯ΠΎΠ»ΠΎΠ΄Π½ΡΠΉ Π±ΡΠΊΠ°ΠΏ ΠΏΡΠΈΠ³ΠΎΠ΄ΠΈΡΡΡ, Π΅ΡΠ»ΠΈ Π²Ρ ΡΠ»ΡΡΠ°ΠΉΠ½ΠΎ ΡΠ΄Π΅Π»Π°Π»ΠΈ DELETE
ΠΈΠ»ΠΈ DROP TABLE
. ΠΡ Π΄Π΅Π»Π°Π΅ΠΌ Π±ΡΠΊΠ°ΠΏ ΠΈΠ· Ρ
ΠΎΠ»ΠΎΠ΄Π½ΠΎΠ³ΠΎ Ρ
ΡΠ°Π½ΠΈΠ»ΠΈΡΠ° ΠΈ Π²ΠΎΡΡΡΠ°Π½Π°Π²Π»ΠΈΠ²Π°Π΅ΠΌ ΠΏΡΠ΅Π΄ΡΠ΄ΡΡΠ΅Π΅ ΡΠΎΡΡΠΎΡΠ½ΠΈΠ΅ ΡΠ°Π±Π»ΠΈΡΡ ΠΈΠ»ΠΈ Π²ΡΠ΅ΠΉ Π±Π°Π·Ρ Π΄Π°Π½Π½ΡΡ
. ΠΠΎ ΠΏΡΠΈ ΡΡΠΎΠΌ Π·Π°ΠΏΡΠΎΡ DROP TABLE
ΠΏΠΎΡΡΠΈ ΠΌΠΎΠΌΠ΅Π½ΡΠ°Π»ΡΠ½ΠΎ Π²ΠΎΡΠΏΡΠΎΠΈΠ·Π²ΠΎΠ΄ΠΈΡΡΡ Π²ΠΎ Π²ΡΠ΅Ρ
ΡΠ΅ΠΏΠ»ΠΈΠΊΠ°Ρ
Π½Π° ΡΠ°Π±ΠΎΡΠ΅ΠΌ ΠΊΠ»Π°ΡΡΠ΅ΡΠ΅, ΠΏΠΎΡΡΠΎΠΌΡ ΠΎΠ±ΡΡΠ½Π°Ρ ΡΠ΅ΠΏΠ»ΠΈΠΊΠ°ΡΠΈΡ ΡΡΡ Π½Π΅ ΡΠΏΠ°ΡΠ΅Ρ. Π‘Π°ΠΌΠ° ΠΏΠΎ ΡΠ΅Π±Π΅ ΡΠ΅ΠΏΠ»ΠΈΠΊΠ°ΡΠΈΡ ΠΏΠΎΠ΄Π΄Π΅ΡΠΆΠΈΠ²Π°Π΅Ρ Π±Π°Π·Ρ Π΄Π°Π½Π½ΡΡ
Π΄ΠΎΡΡΡΠΏΠ½ΠΎΠΉ, ΠΊΠΎΠ³Π΄Π° ΡΠ΄Π°ΡΡ ΠΎΡΠ΄Π΅Π»ΡΠ½ΡΠ΅ ΡΠ΅ΡΠ²Π΅ΡΡ, ΠΈ ΡΠ°ΡΠΏΡΠ΅Π΄Π΅Π»ΡΠ΅Ρ Π½Π°Π³ΡΡΠ·ΠΊΡ.
ΠΠ°ΠΆΠ΅ Ρ ΠΎΡΠ»ΠΎΠΆΠ΅Π½Π½ΠΎΠΉ ΡΠ΅ΠΏΠ»ΠΈΠΊΠΎΠΉ Π½Π°ΠΌ ΠΈΠ½ΠΎΠ³Π΄Π° ΠΎΡΠ΅Π½Ρ Π½ΡΠΆΠ΅Π½ Ρ ΠΎΠ»ΠΎΠ΄Π½ΡΡ Π±ΡΠΊΠ°ΠΏ Π² Π±Π΅Π·ΠΎΠΏΠ°ΡΠ½ΠΎΠΌ ΠΌΠ΅ΡΡΠ΅, Π΅ΡΠ»ΠΈ Π²Π΄ΡΡΠ³ ΠΏΡΠΎΠΈΠ·ΠΎΠΉΠ΄Π΅Ρ ΡΠ±ΠΎΠΉ Π΄Π°ΡΠ°-ΡΠ΅Π½ΡΡΠ°, ΡΠΊΡΡΡΠΎΠ΅ ΠΏΠΎΠ²ΡΠ΅ΠΆΠ΄Π΅Π½ΠΈΠ΅ ΠΈΠ»ΠΈ Π΄ΡΡΠ³ΠΈΠ΅ ΡΠΎΠ±ΡΡΠΈΡ, ΠΊΠΎΡΠΎΡΡΠ΅ ΡΡΠ°Π·Ρ Π½Π΅ Π·Π°ΠΌΠ΅ΡΠΈΡΡ. Π’ΡΡ ΠΎΡ ΠΎΠ΄Π½ΠΎΠΉ ΡΠ΅ΠΏΠ»ΠΈΠΊΠ°ΡΠΈΠΈ ΡΠΎΠ»ΠΊΡ Π½Π΅Ρ.
ΠΡΠΈΠΌΠ΅ΡΠ°Π½ΠΈΠ΅. ΠΠ°
ΠΡΡΠΎΡΠ½ΠΈΠΊ: habr.com