PostgreSQL์—์„œ ์žฌํ•ด ๋ณต๊ตฌ๋ฅผ ์œ„ํ•ด ์ง€์—ฐ ๋ณต์ œ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•

PostgreSQL์—์„œ ์žฌํ•ด ๋ณต๊ตฌ๋ฅผ ์œ„ํ•ด ์ง€์—ฐ ๋ณต์ œ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•
๋ณต์ œ๋Š” ๋ฐฑ์—…์ด ์•„๋‹™๋‹ˆ๋‹ค. ์•„๋‹ˆ๋ฉด? ์‹ค์ˆ˜๋กœ ์‚ญ์ œ๋œ ๋ฐ”๋กœ๊ฐ€๊ธฐ๋ฅผ ๋ณต๊ตฌํ•˜๊ธฐ ์œ„ํ•ด ์ง€์—ฐ ๋ณต์ œ๋ฅผ ์‚ฌ์šฉํ•œ ๋ฐฉ๋ฒ•์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

์ธํ”„๋ผ ์ „๋ฌธ๊ฐ€ GitLab์ด ์ž‘์—…์„ ๋‹ด๋‹นํ•ฉ๋‹ˆ๋‹ค. GitLab.com - ์ž์—ฐ๊ณ„์—์„œ ๊ฐ€์žฅ ํฐ GitLab ์ธ์Šคํ„ด์Šค์ž…๋‹ˆ๋‹ค. 3๋ฐฑ๋งŒ ๋ช…์˜ ์‚ฌ์šฉ์ž์™€ ์•ฝ 7๋ฐฑ๋งŒ ๊ฐœ์˜ ํ”„๋กœ์ ํŠธ๋ฅผ ๋ณด์œ ํ•œ ์ด ์‚ฌ์ดํŠธ๋Š” ์ „์šฉ ์•„ํ‚คํ…์ฒ˜๋ฅผ ๊ฐ–์ถ˜ ์ตœ๋Œ€ ์˜คํ”ˆ ์†Œ์Šค SaaS ์‚ฌ์ดํŠธ ์ค‘ ํ•˜๋‚˜์ž…๋‹ˆ๋‹ค. PostgreSQL ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์‹œ์Šคํ…œ์ด ์—†์œผ๋ฉด GitLab.com ์ธํ”„๋ผ๋Š” ๋ฉ€๋ฆฌ ๊ฐ€์ง€ ๋ชปํ•  ๊ฒƒ์ด๋ฉฐ, ๋ฐ์ดํ„ฐ๊ฐ€ ์†์‹ค๋  ์ˆ˜ ์žˆ๋Š” ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•  ๊ฒฝ์šฐ ๋‚ด๊ฒฐํ•จ์„ฑ์„ ๋ณด์žฅํ•˜๊ธฐ ์œ„ํ•ด ์šฐ๋ฆฌ๋Š” ๋ฌด์—‡์„ ํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๊นŒ? ์ด๋Ÿฌํ•œ ์žฌ๋‚œ์ด ๋ฐœ์ƒํ•  ๊ฐ€๋Šฅ์„ฑ์€ ๊ฑฐ์˜ ์—†์ง€๋งŒ ๋‹ค์–‘ํ•œ ๋ฐฑ์—… ๋ฐ ๋ณต์ œ ๋ฉ”์ปค๋‹ˆ์ฆ˜์„ ์ž˜ ์ค€๋น„ํ•˜๊ณ  ๋น„์ถ•ํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

๋ณต์ œ๋Š” ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋ฅผ ๋ฐฑ์—…ํ•˜๋Š” ์ˆ˜๋‹จ์ด ์•„๋‹™๋‹ˆ๋‹ค(์•„๋ž˜ ์ฐธ์กฐ). ํ•˜์ง€๋งŒ ์ด์ œ ์ง€์—ฐ ๋ณต์ œ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์‹ค์ˆ˜๋กœ ์‚ญ์ œ๋œ ๋ฐ์ดํ„ฐ๋ฅผ ์‹ ์†ํ•˜๊ฒŒ ๋ณต๊ตฌํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. GitLab.com ์‚ฌ์šฉ์ž ๋ฐ”๋กœ๊ฐ€๊ธฐ๋ฅผ ์‚ญ์ œํ–ˆ์Šต๋‹ˆ๋‹ค ํ”„๋กœ์ ํŠธ๋ฅผ ์œ„ํ•ด gitlab-ce ๋ณ‘ํ•ฉ ์š”์ฒญ ๋ฐ ์ž‘์—…๊ณผ์˜ ์—ฐ๊ฒฐ์ด ๋Š์–ด์กŒ์Šต๋‹ˆ๋‹ค.

์ง€์—ฐ๋œ ๋ณต์ œ๋ณธ์„ ์‚ฌ์šฉํ•˜์—ฌ ๋‹จ 1,5์‹œ๊ฐ„ ๋งŒ์— ๋ฐ์ดํ„ฐ๋ฅผ ๋ณต๊ตฌํ–ˆ์Šต๋‹ˆ๋‹ค. ์–ด๋–ป๊ฒŒ ๋œ ์ผ์ธ์ง€ ๋ณด์„ธ์š”.

PostgreSQL์„ ์‚ฌ์šฉํ•œ ํŠน์ • ์‹œ์  ๋ณต๊ตฌ

PostgreSQL์—๋Š” ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์ƒํƒœ๋ฅผ ํŠน์ • ์‹œ์ ์œผ๋กœ ๋ณต์›ํ•˜๋Š” ๊ธฐ๋Šฅ์ด ๋‚ด์žฅ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๊ฒƒ์€์ด๋ผ๊ณ  ํŠน์ • ์‹œ์  ๋ณต๊ตฌ (PITR) ๋ณต์ œ๋ณธ์„ ์ตœ์‹  ์ƒํƒœ๋กœ ์œ ์ง€ํ•˜๋Š” ๊ฒƒ๊ณผ ๋™์ผํ•œ ๋ฉ”์ปค๋‹ˆ์ฆ˜์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ์ „์ฒด ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ํด๋Ÿฌ์Šคํ„ฐ์˜ ์•ˆ์ •์ ์ธ ์Šค๋ƒ…์ƒท(๊ธฐ๋ณธ ๋ฐฑ์—…)๋ถ€ํ„ฐ ์‹œ์ž‘ํ•˜์—ฌ ํŠน์ • ์‹œ์ ๊นŒ์ง€ ์ผ๋ จ์˜ ์ƒํƒœ ๋ณ€๊ฒฝ์„ ์ ์šฉํ•ฉ๋‹ˆ๋‹ค.

์ฝœ๋“œ ๋ฐฑ์—…์— ์ด ๊ธฐ๋Šฅ์„ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด ์šฐ๋ฆฌ๋Š” ์ •๊ธฐ์ ์œผ๋กœ ๊ธฐ๋ณธ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๋ฐฑ์—…์„ ๋งŒ๋“ค์–ด ์•„์นด์ด๋ธŒ์— ์ €์žฅํ•ฉ๋‹ˆ๋‹ค(GitLab ์•„์นด์ด๋ธŒ๋Š” ๊ตฌ๊ธ€ ํด๋ผ์šฐ๋“œ ์Šคํ† ๋ฆฌ์ง€). ๋˜ํ•œ ๋ฏธ๋ฆฌ ์“ฐ๊ธฐ ๋กœ๊ทธ๋ฅผ ๋ณด๊ด€ํ•˜์—ฌ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์ƒํƒœ์˜ ๋ณ€๊ฒฝ ์‚ฌํ•ญ์„ ๋ชจ๋‹ˆํ„ฐ๋งํ•ฉ๋‹ˆ๋‹ค(๋ฏธ๋ฆฌ ์“ฐ๊ธฐ ๋กœ๊ทธ, ์›”). ๊ทธ๋ฆฌ๊ณ  ์ด ๋ชจ๋“  ๊ฒƒ์ด ์ค€๋น„๋˜๋ฉด ์žฌํ•ด ๋ณต๊ตฌ๋ฅผ ์œ„ํ•œ PITR์„ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•˜๊ธฐ ์ „์— ์ฐ์€ ์Šค๋ƒ…์ƒท๋ถ€ํ„ฐ ์‹œ์ž‘ํ•˜์—ฌ WAL ์•„์นด์ด๋ธŒ์˜ ๋ณ€๊ฒฝ ์‚ฌํ•ญ์„ ์˜ค๋ฅ˜๊นŒ์ง€ ์ ์šฉํ•ฉ๋‹ˆ๋‹ค.

์ง€์—ฐ ๋ณต์ œ๋ž€ ๋ฌด์—‡์ž…๋‹ˆ๊นŒ?

์ง€์—ฐ ๋ณต์ œ๋Š” WAL์˜ ๋ณ€๊ฒฝ ์‚ฌํ•ญ์„ ์ง€์—ฐํ•˜์—ฌ ์ ์šฉํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ฆ‰, ๊ฑฐ๋ž˜๊ฐ€ ํ•œ ์‹œ๊ฐ„ ์•ˆ์— ์ด๋ฃจ์–ด์กŒ์Šต๋‹ˆ๋‹ค. X, ๊ทธ๋Ÿฌ๋‚˜ ์ง€์—ฐ๊ณผ ํ•จ๊ป˜ ๋ณต์ œ๋ณธ์— ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค. d 1์‹œ์— X + d.

PostgreSQL์—๋Š” ๋ฌผ๋ฆฌ์  ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๋ณต์ œ๋ณธ์„ ์„ค์ •ํ•˜๋Š” ๋‘ ๊ฐ€์ง€ ๋ฐฉ๋ฒ•, ์ฆ‰ ๋ฐฑ์—… ๋ณต๊ตฌ์™€ ์ŠคํŠธ๋ฆฌ๋ฐ ๋ณต์ œ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ์•„์นด์ด๋ธŒ์—์„œ ๋ณต์›, ๊ธฐ๋ณธ์ ์œผ๋กœ 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 ์„ธ๊ทธ๋จผํŠธ๋ฅผ ์ถ”์ถœํ•˜๋ ค๋ฉด(restore_command) ์•„์นด์ด๋ธŒ์—์„œ ์‚ญ์ œ๋˜๋ฉฐ ๋ณ€๊ฒฝ์‚ฌํ•ญ์€ XNUMX์‹œ๊ฐ„(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). ๋ณด์‹œ๋‹ค์‹œํ”ผ ์ง€์—ฐ์€ ์ปค๋ฐ‹์—๋งŒ ์ ์šฉ๋˜๋ฉฐ ๋‹ค๋ฅธ ํ•ญ๋ชฉ์—๋Š” ์˜ํ–ฅ์„ ์ฃผ์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๋ชจ๋“  ๋ณ€๊ฒฝ ์‚ฌํ•ญ์€ ์ง์ ‘ ์ ์šฉ๋˜๊ณ  ์ปค๋ฐ‹์ด ์ง€์—ฐ๋˜๋ฏ€๋กœ ๊ตฌ์„ฑ๋œ ์ง€์—ฐ ํ›„์—๋งŒ ๋ณ€๊ฒฝ ์‚ฌํ•ญ์ด ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค.

์ง€์—ฐ๋œ ๋ณต์ œ๋ณธ์„ ์‚ฌ์šฉํ•˜์—ฌ ๋ฐ์ดํ„ฐ๋ฅผ ๋ณต์›ํ•˜๋Š” ๋ฐฉ๋ฒ•

ํ”„๋กœ๋•์…˜์ด XNUMX์‹œ๊ฐ„ ์ง€์—ฐ๋œ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ํด๋Ÿฌ์Šคํ„ฐ์™€ ๋ณต์ œ๋ณธ์ด ์žˆ๋‹ค๊ณ  ๊ฐ€์ •ํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. ์˜ˆ์ œ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ฐ์ดํ„ฐ๋ฅผ ๋ณต๊ตฌํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์‚ดํŽด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. ์‹ค์ˆ˜๋กœ ๋ฐ”๋กœ๊ฐ€๊ธฐ ์‚ญ์ œ.

๋ฌธ์ œ์— ๋Œ€ํ•ด ์•Œ๊ฒŒ ๋˜์—ˆ์„ ๋•Œ ์šฐ๋ฆฌ๋Š” ์•„์นด์ด๋ธŒ ๋ณต์›์ด ์ผ์‹œ ์ค‘์ง€๋˜์—ˆ์Šต๋‹ˆ๋‹ค ์ง€์—ฐ๋œ ๋ณต์ œ๋ณธ์˜ ๊ฒฝ์šฐ:

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๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ๋” ์ข‹์Šต๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด DDL ๋ฌธ(์˜ˆ: DROP TABLE), ์‚ฌ์šฉํ•˜์—ฌ log_statements = 'ddl'. ๊ฑฐ๋ž˜ ID๊ฐ€ ์žˆ๋‹ค๋ฉด recovery_target_xid ์š”์ฒญ ์ „์— ํŠธ๋žœ์žญ์…˜๊นŒ์ง€ ๋ชจ๋“  ๊ฒƒ์„ ์‹คํ–‰ํ–ˆ์Šต๋‹ˆ๋‹ค. DELETE.

์ž‘์—…์œผ๋กœ ๋Œ์•„๊ฐ€๋Š” ๊ฒƒ์€ ๋งค์šฐ ๊ฐ„๋‹จํ•ฉ๋‹ˆ๋‹ค. ๋ชจ๋“  ๋ณ€๊ฒฝ ์‚ฌํ•ญ์„ ์ œ๊ฑฐํ•˜์„ธ์š”. recovery.conf Postgres๋ฅผ ๋‹ค์‹œ ์‹œ์ž‘ํ•˜์‹ญ์‹œ์˜ค. ๋ณต์ œ๋ณธ์€ ๊ณง ๋‹ค์‹œ XNUMX์‹œ๊ฐ„ ์ง€์—ฐ๋  ์˜ˆ์ •์ด๋ฉฐ ํ–ฅํ›„ ๋ฌธ์ œ์— ๋Œ€๋น„ํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

ํšŒ๋ณต ํ˜œํƒ

์ฝœ๋“œ ๋ฐฑ์—… ๋Œ€์‹  ์ง€์—ฐ๋œ ๋ณต์ œ๋ณธ์„ ์‚ฌ์šฉํ•˜๋ฉด ์•„์นด์ด๋ธŒ์—์„œ ์ „์ฒด ์ด๋ฏธ์ง€๋ฅผ ๋ณต์›ํ•˜๋Š” ๋ฐ ๋ช‡ ์‹œ๊ฐ„์„ ์†Œ๋น„ํ•  ํ•„์š”๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด ๊ธฐ๋ณธ 2TB ๋ฐฑ์—… ์ „์ฒด๋ฅผ ๊ฐ€์ ธ์˜ค๋Š” ๋ฐ XNUMX์‹œ๊ฐ„์ด ๊ฑธ๋ฆฝ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฐ ๋‹ค์Œ ์›ํ•˜๋Š” ์ƒํƒœ(์ตœ์•…์˜ ๊ฒฝ์šฐ)๋กœ ๋ณต๊ตฌํ•˜๋ ค๋ฉด ์ „์ฒด ์ผ์ผ WAL์„ ์ ์šฉํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

์ง€์—ฐ๋œ ๋ณต์ œ๋ณธ์€ ๋‘ ๊ฐ€์ง€ ์ธก๋ฉด์—์„œ ์ฝœ๋“œ ๋ฐฑ์—…๋ณด๋‹ค ์šฐ์ˆ˜ํ•ฉ๋‹ˆ๋‹ค.

  1. ์•„์นด์ด๋ธŒ์—์„œ ์ „์ฒด ๊ธฐ๋ณธ ๋ฐฑ์—…์„ ์ œ๊ฑฐํ•  ํ•„์š”๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค.
  2. ๋ฐ˜๋ณตํ•ด์•ผ ํ•˜๋Š” WAL ์„ธ๊ทธ๋จผํŠธ์˜ ๊ณ ์ •๋œ XNUMX์‹œ๊ฐ„ ๊ธฐ๊ฐ„์ด ์žˆ์Šต๋‹ˆ๋‹ค.

๋˜ํ•œ WAL์—์„œ PITR์„ ๋งŒ๋“œ๋Š” ๊ฒƒ์ด ๊ฐ€๋Šฅํ•œ์ง€ ์ง€์†์ ์œผ๋กœ ํ™•์ธํ•˜๊ณ  ์ง€์—ฐ๋œ ๋ณต์ œ๋ณธ์˜ ์ง€์—ฐ์„ ๋ชจ๋‹ˆํ„ฐ๋งํ•˜์—ฌ WAL ์•„์นด์ด๋ธŒ์˜ ์†์ƒ์ด๋‚˜ ๊ธฐํƒ€ ๋ฌธ์ œ๋ฅผ ์‹ ์†ํ•˜๊ฒŒ ๋ฐœ๊ฒฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ด ์˜ˆ์—์„œ๋Š” ๋ณต์›ํ•˜๋Š” ๋ฐ 50๋ถ„์ด ๊ฑธ๋ ธ์Šต๋‹ˆ๋‹ค. ์ฆ‰, ์†๋„๋Š” ์‹œ๊ฐ„๋‹น 110GB์˜ WAL ๋ฐ์ดํ„ฐ์˜€์Šต๋‹ˆ๋‹ค(์•„์นด์ด๋ธŒ๋Š” ์—ฌ์ „ํžˆ ๋‚จ์•„ ์žˆ์Œ). AWS S3). ์ „์ฒด์ ์œผ๋กœ ์šฐ๋ฆฌ๋Š” ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๊ณ  1,5์‹œ๊ฐ„ ๋งŒ์— ๋ฐ์ดํ„ฐ๋ฅผ ๋ณต๊ตฌํ–ˆ์Šต๋‹ˆ๋‹ค.

๊ฒฐ๊ณผ: ์ง€์—ฐ๋œ ๋ณต์ œ๋ณธ์ด ์œ ์šฉํ•œ ๊ฒฝ์šฐ์™€ ๊ทธ๋ ‡์ง€ ์•Š์€ ๊ฒฝ์šฐ

์‹ค์ˆ˜๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ์†์‹คํ•˜๊ณ  ๊ตฌ์„ฑ๋œ ์ง€์—ฐ ๋‚ด์— ์ด ๋ฌธ์ œ๋ฅผ ๋ฐœ๊ฒฌํ•œ ๊ฒฝ์šฐ ์ง€์—ฐ๋œ ๋ณต์ œ๋ฅผ ์‘๊ธ‰ ์ฒ˜์น˜๋กœ ์‚ฌ์šฉํ•˜์‹ญ์‹œ์˜ค.

ํ•˜์ง€๋งŒ ๋ช…์‹ฌํ•˜์„ธ์š”: ๋ณต์ œ๋Š” ๋ฐฑ์—…์ด ์•„๋‹™๋‹ˆ๋‹ค.

๋ฐฑ์—…๊ณผ ๋ณต์ œ๋Š” ๋ชฉ์ ์ด ๋‹ค๋ฆ…๋‹ˆ๋‹ค. ์‹ค์ˆ˜๋กœ ๋งŒ๋“  ๊ฒฝ์šฐ ์ฝœ๋“œ ๋ฐฑ์—…์ด ์œ ์šฉํ•ฉ๋‹ˆ๋‹ค. DELETE ๋˜๋Š” DROP TABLE. ์ฝœ๋“œ ์Šคํ† ๋ฆฌ์ง€์—์„œ ๋ฐฑ์—…์„ ๋งŒ๋“ค๊ณ  ํ…Œ์ด๋ธ” ๋˜๋Š” ์ „์ฒด ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์˜ ์ด์ „ ์ƒํƒœ๋ฅผ ๋ณต์›ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ๋™์‹œ์— ์š”์ฒญ DROP TABLE ์ž‘์—… ํด๋Ÿฌ์Šคํ„ฐ์˜ ๋ชจ๋“  ๋ณต์ œ๋ณธ์—์„œ ๊ฑฐ์˜ ์ฆ‰๊ฐ์ ์œผ๋กœ ๋ณต์ œ๋˜๋ฏ€๋กœ ์—ฌ๊ธฐ์„œ๋Š” ์ผ๋ฐ˜์ ์ธ ๋ณต์ œ๊ฐ€ ๋„์›€์ด ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๋ณต์ œ ์ž์ฒด๋Š” ๊ฐœ๋ณ„ ์„œ๋ฒ„๋ฅผ ์ž„๋Œ€ํ•˜๊ณ  ๋กœ๋“œ๋ฅผ ๋ถ„์‚ฐํ•  ๋•Œ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋ฅผ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ์ƒํƒœ๋กœ ์œ ์ง€ํ•ฉ๋‹ˆ๋‹ค.

์ง€์—ฐ๋œ ๋ณต์ œ๋ณธ์„ ์‚ฌ์šฉํ•˜๋”๋ผ๋„ ๋ฐ์ดํ„ฐ ์„ผํ„ฐ ์˜ค๋ฅ˜, ์ˆจ๊ฒจ์ง„ ์†์ƒ ๋˜๋Š” ์ฆ‰์‹œ ๋ˆˆ์— ๋„์ง€ ์•Š๋Š” ๊ธฐํƒ€ ์ด๋ฒคํŠธ๊ฐ€ ๋ฐœ์ƒํ•  ๊ฒฝ์šฐ ์•ˆ์ „ํ•œ ์žฅ์†Œ์— ์ฝœ๋“œ ๋ฐฑ์—…์ด ํ•„์š”ํ•œ ๊ฒฝ์šฐ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์„œ๋Š” ๋ณต์ œ๋งŒ์œผ๋กœ๋Š” ์†Œ์šฉ์ด ์—†์Šต๋‹ˆ๋‹ค.

์ฃผ์˜. ์— GitLab.com ํ˜„์žฌ๋Š” ์‹œ์Šคํ…œ ์ˆ˜์ค€์˜ ๋ฐ์ดํ„ฐ ์†์‹ค๋งŒ ๋ฐฉ์ง€ํ•˜๊ณ  ์‚ฌ์šฉ์ž ์ˆ˜์ค€์˜ ๋ฐ์ดํ„ฐ๋Š” ๋ณต๊ตฌํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

์ถœ์ฒ˜ : habr.com

์ฝ”๋ฉ˜ํŠธ๋ฅผ ์ถ”๊ฐ€