PostgreSQL - Folyamatos archiválás
A RoolWikiBÓL
2007. október 15., 14:35 változat (szerkesztés) Rozsahegyil (Vita | szerkesztései) (→Létrehozzuk a backup adatbázist) ← Előző változtatások |
Aktuális változat (2008. április 1., 14:27) (szerkesztés) (undo) Rozsahegyil (Vita | szerkesztései) A (→Az archiválás leállítása) |
||
(10 intermediate revisions not shown.) | |||
1. sor: | 1. sor: | ||
Ez a folyamatos archiválás teszt és dokumentáció a [http://www.postgresql.org/docs/8.2/interactive/continuous-archiving.html 23.3. Continuous Archiving and Point-In-Time Recovery (PITR)] és a [http://developer.postgresql.org/pgdocs/postgres/warm-standby.html] postgresql dokumentáció alapján készült. | Ez a folyamatos archiválás teszt és dokumentáció a [http://www.postgresql.org/docs/8.2/interactive/continuous-archiving.html 23.3. Continuous Archiving and Point-In-Time Recovery (PITR)] és a [http://developer.postgresql.org/pgdocs/postgres/warm-standby.html] postgresql dokumentáció alapján készült. | ||
- | A cél egy másik számítógépre duplikálni a fő adatbázist, úgy hogy folyamatosan - a lehető leginkább - naprakész legyen. | + | A cél egy másik számítógépre duplikálni a fő adatbázist úgy, hogy folyamatosan - a lehető leginkább - naprakész legyen. |
Ha a fő rendszer bármilyen hiba miatt működésképtelenné válik, akkor ez a biztonsági léphet a helyébe. | Ha a fő rendszer bármilyen hiba miatt működésképtelenné válik, akkor ez a biztonsági léphet a helyébe. | ||
A biztonsági adatbázis nem hozzáférhető ebben az üzemmódban. A használatba állításához le kell állítani a folytonos mentés funkcióját. | A biztonsági adatbázis nem hozzáférhető ebben az üzemmódban. A használatba állításához le kell állítani a folytonos mentés funkcióját. | ||
19. sor: | 19. sor: | ||
(egy sorba kell írni a parancsot!) | (egy sorba kell írni a parancsot!) | ||
- | Elő lehet írni, hogy ha egy megadott időn belül nem készül wal log fájl, akkor készítse el: | + | Elő lehet írni, hogy ha egy megadott időn belül nem készül wal log fájl (mert nem történt elegendő változás), akkor készítse el: |
archive_timeout = 1h | archive_timeout = 1h | ||
54. sor: | 54. sor: | ||
** Töröljük a data/serverlog, data/postgresql.pid fájlt! | ** Töröljük a data/serverlog, data/postgresql.pid fájlt! | ||
** Szerkesszük át a postgresql.conf fáljt: ne legyen bekapcsolva a wal archiválás! | ** Szerkesszük át a postgresql.conf fáljt: ne legyen bekapcsolva a wal archiválás! | ||
- | archive_command = <két egymást követő aposztróf> | + | archive_command = '' |
archive_timeout = 0 | archive_timeout = 0 | ||
63. sor: | 63. sor: | ||
* Indítsuk el a szervert! | * Indítsuk el a szervert! | ||
- | Ezt nálunk egy szkript elvégzi: | + | <small>Az archiv fájl kicsomagolását és a törléseket nálunk egy szkript elvégzi: |
[ -d /uhu/pgsql8.2.3/data ] && echo Először törölni kell a data mappát! && exit 1 | [ -d /uhu/pgsql8.2.3/data ] && echo Először törölni kell a data mappát! && exit 1 | ||
90. sor: | 90. sor: | ||
exit 0 | exit 0 | ||
+ | </small> | ||
Ekkor nem lesz folytonos a mentés. Induláskor amíg talál wal szegmenst, addig azokat betölti, de ezután leáll a visszaállító mód. Ezután hiába jönnek létre a fő szerveren wal szegmensek, azok nem kerülnek át a biztonsági szerverre. A "restore commnad" minden wal szegmensre ki lesz adva, ha az nincs a pg_xlog mappában. Ha egy olyan parancsot írunk ide (lehet egy szkript is), ami addig vár, amíg elérhető nem lesz a következő szegmens, majd végrehajtja a másolást, akkor elérhető a folyamatos mentés. Ezzel magyarázható az is, hogy a biztonsági adatbázis nem használható lekérdezésre. | Ekkor nem lesz folytonos a mentés. Induláskor amíg talál wal szegmenst, addig azokat betölti, de ezután leáll a visszaállító mód. Ezután hiába jönnek létre a fő szerveren wal szegmensek, azok nem kerülnek át a biztonsági szerverre. A "restore commnad" minden wal szegmensre ki lesz adva, ha az nincs a pg_xlog mappában. Ha egy olyan parancsot írunk ide (lehet egy szkript is), ami addig vár, amíg elérhető nem lesz a következő szegmens, majd végrehajtja a másolást, akkor elérhető a folyamatos mentés. Ezzel magyarázható az is, hogy a biztonsági adatbázis nem használható lekérdezésre. | ||
101. sor: | 102. sor: | ||
A get_wal.sh program: | A get_wal.sh program: | ||
- | #!/bin/bash | + | #!/bin/bash |
- | <br> | + | |
- | SOURCE=$1 | + | #exit 100 |
- | TARGET=$2 | + | |
- | OK=0 | + | SOURCE=$1 |
- | LOGFILE=masol.txt | + | TARGET=$2 |
- | <br> | + | OK=0 |
- | SIZE_EXPECTED=16777216 #bytes 16 MB | + | LOGFILE=masol.txt |
- | <br> | + | WAL_DIR=/uhu/pgsql8.2.3/wal |
- | echo >> $LOGFILE | + | WAL_FILE=$WAL_DIR/$SOURCE |
- | echo $SOURCE >> $LOGFILE | + | SOURCE_PATH=192.168.1.13:/home/postgres/wal_ahead_log_8.2.3 |
- | COUNTER=0 | + | SIZE_EXPECTED=16777216 #bytes 16 MB |
- | WRONG_SIZE_COUNTER=0 | + | |
- | <br> | + | echo >> $LOGFILE |
- | if [ $SOURCE == "00000001.history" ] | + | echo $SOURCE >> $LOGFILE |
- | then | + | COUNTER=0 |
- | exit 1 | + | WRONG_SIZE_COUNTER=0 |
- | fi | + | |
- | <br> | + | if [ $SOURCE == "00000001.history" ] |
- | while [ 1 ] | + | then |
- | do | + | exit 1 |
- | echo `date` Copy $SOURCE to $TARGET >> $LOGFILE | + | fi |
- | scp 192.168.1.13:/home/postgres/wal_ahead_log_8.2.3/$SOURCE $TARGET >> $LOGFILE | + | |
- | RET=$? | + | while [ 1 ] |
- | echo Copy returns $RET >> $LOGFILE | + | do |
- | if [ "$RET" -ne "0" ] | + | echo `date` Copy $SOURCE_PATH/$SOURCE to $WAL_FILE >> $LOGFILE |
- | then | + | scp $SOURCE_PATH/$SOURCE $WAL_FILE 2>&1 >> $LOGFILE |
- | ((COUNTER++)) | + | RET=$? |
- | echo $COUNTER. returns $RET >> $LOGFILE | + | echo Copy returns $RET >> $LOGFILE |
- | if [ $COUNTER -gt 10 ] | + | if [ "$RET" -ne "0" ] |
- | then | + | then |
- | exit 1 | + | ((COUNTER++)) |
- | fi | + | echo $COUNTER. returns $RET >> $LOGFILE |
- | echo sleep 10 minutes >> $LOGFILE | + | if [ $COUNTER -gt 10 ] |
- | sleep 10m | + | then |
- | else | + | exit 1 |
- | if [ -f $TARGET ] | + | fi |
- | then | + | echo sleep 10 minutes >> $LOGFILE |
- | TARGET_SIZE=$(stat -c '%s' ${TARGET}) | + | sleep 10m |
- | else | + | else |
- | TARGET_SIZE=-1 | + | TARGET_SIZE=-1 |
- | fi | + | [ -f $WAL_FILE ] && TARGET_SIZE=$(stat -c '%s' ${WAL_FILE}) |
- | echo target size is $TARGET_SIZE >> $LOGFILE | + | echo target size is $TARGET_SIZE >> $LOGFILE |
- | if [ $TARGET_SIZE -eq $SIZE_EXPECTED ] | + | if [ $TARGET_SIZE -eq $SIZE_EXPECTED ] |
- | then | + | then |
- | echo done. >> $LOGFILE | + | echo file is ok. >> $LOGFILE |
- | exit 0 | + | echo rm last before wal >> $LOGFILE && rm -f $WAL_DIR/last/* && echo [ok] >> $LOGFILE |
- | else | + | |
- | ((WRONG_SIZE_COUNTER++)) | + | echo copy $WAL_FILE to $TARGET >> $LOGFILE && cp $WAL_FILE $TARGET && echo [ok] >> $LOGFILE |
- | echo $WRONG_SIZE_COUNTER. wrong size: $TARGET_SIZE >> $LOGFILE | + | |
- | if [ $WRONG_SIZE_COUNTER -gt 1 ] | + | echo copy $WAL_FILE to $WAL_DIR/last/$SOURCE >> $LOGFILE && mv $WAL_FILE $WAL_DIR/last/$SOURCE && echo [ok] >> $LOGFILE |
- | then | + | |
- | exit 0 | + | echo safe copy done. >> $LOGFILE |
- | fi | + | exit 0 |
- | echo sleep 1 minute >> $LOGFILE | + | else |
- | sleep 1m | + | ((WRONG_SIZE_COUNTER++)) |
- | fi | + | echo $WRONG_SIZE_COUNTER. wrong size: $TARGET_SIZE >> $LOGFILE |
- | fi | + | if [ $WRONG_SIZE_COUNTER -gt 1 ] |
- | done | + | then |
- | <br> | + | exit 0 |
- | echo "HIBA" >> $LOGFILE | + | fi |
+ | echo "sleep 1 minute (wrong size)" >> $LOGFILE | ||
+ | sleep 1m | ||
+ | fi | ||
+ | fi | ||
+ | done | ||
+ | |||
+ | echo "OK" >> $LOGFILE | ||
=== Az archiválás leállítása === | === Az archiválás leállítása === | ||
- | * Szabványos módon leállítjuk a PostgreSQL adatbázis szervert. | + | * Szabványos módon (szabályosan) leállítjuk a PostgreSQL adatbázis szervert. |
/etc/init.d/postgresql8.2.3 stop | /etc/init.d/postgresql8.2.3 stop | ||
- | * Kicseréljük az visszaállító parancsot (restore_command), hogy ne várjon a következő archive log elkészültére, de ha létezik a kért fájl, akkor azt másolja a megadott helyre. | + | * Kicseréljük a visszaállító parancsot (restore_command), hogy ne várjon a következő archive log elkészültére, de ha létezik a kért fájl, akkor azt másolja a megadott helyre. |
scp 192.168.1.13:/home/postgres/wal_ahead_log_8.2.3/%f %p | scp 192.168.1.13:/home/postgres/wal_ahead_log_8.2.3/%f %p | ||
176. sor: | 184. sor: | ||
/etc/init.d/postgresql8.2.3 start | /etc/init.d/postgresql8.2.3 start | ||
- | |||
Az utolsó - a leállítás előtt sikeresen betöltött - archive logot fogja még kérni a szerver, majd - ha időközben több nem jött létre - befejezi a visszaállító módot (database system is ready). | Az utolsó - a leállítás előtt sikeresen betöltött - archive logot fogja még kérni a szerver, majd - ha időközben több nem jött létre - befejezi a visszaállító módot (database system is ready). | ||
+ | |||
+ | === A biztonsági szerver élesítése, ha a fő szerver elromlik === | ||
+ | |||
+ | * Egyik lehetőség, hogy kivárjuk azt az időt, amíg a "if [ $COUNTER -gt 10 ]" parancs miatt az archiválás leáll, majd használhatjuk a szervert. A fenti szkriptben 10-szer próbáljuk a másolást, 10 perces szünetekkel, így maximum 100 percet kell várni. Ez az idő csökkenthető az ismétlés számának és/vagy a várakozási időnek a csökkentésével. Arra kell figyelni, hogy biztosított legyen a wal szegmens elkészülte a maximális várakozási időn belül, ami az ismétlés*várakozás. Ha ez nincs így, akkor előfordulhat az archiválás leállása a főszerver szabályos működése közben is. Ezért legyen az archive_timeout < (ismétlés-1) * várakozás. | ||
+ | |||
+ | * Ha sürgősen kell, akkor | ||
+ | ** szabályosan leállítjuk a PostgreSQL adatbázis szervert. | ||
+ | ** az utolsó wal szegmenst bemásoljuk a pg_xlog mappába (a restore command biztosítja ennek a fáljnak a meglétét) | ||
+ | cp /uhu/pgsql8.2.3/wal/last/* /uhu/pgsql8.2.3/data/pg_xlog | ||
+ | ** kitöröljük a recovery.conf fájlt | ||
+ | ** újraindítjuk a PostgreSQL adatbázis szervert. | ||
+ | |||
+ | Fontos, hogy a mentést végző adatbázis szerver egynél többször ne legyen leállítva úgy, hogy nem érhető el számára a kért wal szegmens, mert az adatvesztéshez vezethet. (Ezt a logfájljában jelzi ilyen esetben.) |
Aktuális változat
Ez a folyamatos archiválás teszt és dokumentáció a 23.3. Continuous Archiving and Point-In-Time Recovery (PITR) és a [1] postgresql dokumentáció alapján készült.
A cél egy másik számítógépre duplikálni a fő adatbázist úgy, hogy folyamatosan - a lehető leginkább - naprakész legyen. Ha a fő rendszer bármilyen hiba miatt működésképtelenné válik, akkor ez a biztonsági léphet a helyébe. A biztonsági adatbázis nem hozzáférhető ebben az üzemmódban. A használatba állításához le kell állítani a folytonos mentés funkcióját.
Tartalomjegyzék |
Engedélyezzük a WAL log archiválást
A postgresql.conf fájlban az archive_command változónak kell értéket adni. pl:
archive_command = ' echo %f >> /home/postgres/wal_ahead_log_8.2.3/date && date >> /home/postgres/wal_ahead_log_8.2.3/date && test ! -f /home/postgres/wal_ahead_log_8.2.3/%f && echo copy >> /home/postgres/wal_ahead_log_8.2.3/date && cp %p /home/postgres/wal_ahead_log_8.2.3/%f '
(egy sorba kell írni a parancsot!) Elő lehet írni, hogy ha egy megadott időn belül nem készül wal log fájl (mert nem történt elegendő változás), akkor készítse el:
archive_timeout = 1h
A wal_ahead_log_8.2.3 mappában összegyűlt fájlokat majd egy másik hoszton működő szerver fogja magához másolni, amikor szüksége van rá. Ezt az scp paranccsal teszi. Mivel a másolás a háttérben történik, be kell állítani, hogy az scp ne kérjen jelszót.
Újra kell olvastatni a postgresql-el a konfigurációs fájlokat.
/etc/init.d/postgresql8.2.3 reload
Készíteni kell egy alap mentést
- Működjön a wal logok archiválása!
- Be kell lépni a backup módba.
select pg_start_backup('label');
- Fájlrendszer szintű mentést kell készíteni
tar cjf data.backup.tbz2 data
- backup mód vége
select pg_stop_backup();
Befejezi a backup módot. Kiírja az utolsó wal szegmens számát. Eddig felhasználva a wal szegmenseket (azaz log fájlokat) a stop backuppal azonos állapotú adatbázis jön majd létre.
Létrehozzuk a backup adatbázist
- PostgreSQL telepítése a backup gépre. (Ugyanaz a verzió legyen mint a forrás rendszeren!)
- A data.backup.tbz2 kicsomagolása
- Töröljük a data/pg_log, data/pg_xlog és data/pg_xlog/archive_status mappákból a fájlokat
- Töröljük a data/serverlog, data/postgresql.pid fájlt!
- Szerkesszük át a postgresql.conf fáljt: ne legyen bekapcsolva a wal archiválás!
archive_command = '' archive_timeout = 0
- A data mappában létre kell hozni egy recovery.conf állományt. Ez tartalmazza a rendszer visszaállítást vezérlő paramétereket. Nekünk most a következő kell:
restore_command = 'scp 192.168.1.13:/home/postgres/wal_ahead_log_8.2.3/%f %p'
- Indítsuk el a szervert!
Az archiv fájl kicsomagolását és a törléseket nálunk egy szkript elvégzi:
[ -d /uhu/pgsql8.2.3/data ] && echo Először törölni kell a data mappát! && exit 1 echo Új data létrehozása. cd /uhu/pgsql8.2.3
DATABACKUP=data.backup.tbz2
[ ! -f $DATABACKUP ] && echo Nem létezik a $DATABACKUP fájl. && exit 2 tar xjf $DATABACKUP
echo Új data inicializálása. cd ./data
rm postmaster.pid rm -r pg_log/* rm pg_xlog/0* rm -r pg_xlog/safe rm pg_xlog/archive_status/*
cp ../postgresql.conf . cp ../recovery.conf . cp ../000* pg_xlog/
echo Új data kész. exit 0
Ekkor nem lesz folytonos a mentés. Induláskor amíg talál wal szegmenst, addig azokat betölti, de ezután leáll a visszaállító mód. Ezután hiába jönnek létre a fő szerveren wal szegmensek, azok nem kerülnek át a biztonsági szerverre. A "restore commnad" minden wal szegmensre ki lesz adva, ha az nincs a pg_xlog mappában. Ha egy olyan parancsot írunk ide (lehet egy szkript is), ami addig vár, amíg elérhető nem lesz a következő szegmens, majd végrehajtja a másolást, akkor elérhető a folyamatos mentés. Ezzel magyarázható az is, hogy a biztonsági adatbázis nem használható lekérdezésre.
A folytonos archiválást biztosító program
A recovery.conf tartalma ekkor a következő lesz:
restore_command = '/uhu/pgsql8.2.3/bin/get_wal.sh %f %p'
A get_wal.sh program:
#!/bin/bash
#exit 100
SOURCE=$1 TARGET=$2 OK=0 LOGFILE=masol.txt WAL_DIR=/uhu/pgsql8.2.3/wal WAL_FILE=$WAL_DIR/$SOURCE SOURCE_PATH=192.168.1.13:/home/postgres/wal_ahead_log_8.2.3 SIZE_EXPECTED=16777216 #bytes 16 MB
echo >> $LOGFILE echo $SOURCE >> $LOGFILE COUNTER=0 WRONG_SIZE_COUNTER=0
if [ $SOURCE == "00000001.history" ] then exit 1 fi
while [ 1 ] do echo `date` Copy $SOURCE_PATH/$SOURCE to $WAL_FILE >> $LOGFILE scp $SOURCE_PATH/$SOURCE $WAL_FILE 2>&1 >> $LOGFILE RET=$? echo Copy returns $RET >> $LOGFILE if [ "$RET" -ne "0" ] then ((COUNTER++)) echo $COUNTER. returns $RET >> $LOGFILE if [ $COUNTER -gt 10 ] then exit 1 fi echo sleep 10 minutes >> $LOGFILE sleep 10m else TARGET_SIZE=-1 [ -f $WAL_FILE ] && TARGET_SIZE=$(stat -c '%s' ${WAL_FILE}) echo target size is $TARGET_SIZE >> $LOGFILE if [ $TARGET_SIZE -eq $SIZE_EXPECTED ] then echo file is ok. >> $LOGFILE echo rm last before wal >> $LOGFILE && rm -f $WAL_DIR/last/* && echo [ok] >> $LOGFILE
echo copy $WAL_FILE to $TARGET >> $LOGFILE && cp $WAL_FILE $TARGET && echo [ok] >> $LOGFILE
echo copy $WAL_FILE to $WAL_DIR/last/$SOURCE >> $LOGFILE && mv $WAL_FILE $WAL_DIR/last/$SOURCE && echo [ok] >> $LOGFILE
echo safe copy done. >> $LOGFILE exit 0 else ((WRONG_SIZE_COUNTER++)) echo $WRONG_SIZE_COUNTER. wrong size: $TARGET_SIZE >> $LOGFILE if [ $WRONG_SIZE_COUNTER -gt 1 ] then exit 0 fi echo "sleep 1 minute (wrong size)" >> $LOGFILE sleep 1m fi fi done
echo "OK" >> $LOGFILE
Az archiválás leállítása
- Szabványos módon (szabályosan) leállítjuk a PostgreSQL adatbázis szervert.
/etc/init.d/postgresql8.2.3 stop
- Kicseréljük a visszaállító parancsot (restore_command), hogy ne várjon a következő archive log elkészültére, de ha létezik a kért fájl, akkor azt másolja a megadott helyre.
scp 192.168.1.13:/home/postgres/wal_ahead_log_8.2.3/%f %p
- újraindítjuk a PostgreSQL adatbázis szervert.
/etc/init.d/postgresql8.2.3 start
Az utolsó - a leállítás előtt sikeresen betöltött - archive logot fogja még kérni a szerver, majd - ha időközben több nem jött létre - befejezi a visszaállító módot (database system is ready).
A biztonsági szerver élesítése, ha a fő szerver elromlik
- Egyik lehetőség, hogy kivárjuk azt az időt, amíg a "if [ $COUNTER -gt 10 ]" parancs miatt az archiválás leáll, majd használhatjuk a szervert. A fenti szkriptben 10-szer próbáljuk a másolást, 10 perces szünetekkel, így maximum 100 percet kell várni. Ez az idő csökkenthető az ismétlés számának és/vagy a várakozási időnek a csökkentésével. Arra kell figyelni, hogy biztosított legyen a wal szegmens elkészülte a maximális várakozási időn belül, ami az ismétlés*várakozás. Ha ez nincs így, akkor előfordulhat az archiválás leállása a főszerver szabályos működése közben is. Ezért legyen az archive_timeout < (ismétlés-1) * várakozás.
- Ha sürgősen kell, akkor
- szabályosan leállítjuk a PostgreSQL adatbázis szervert.
- az utolsó wal szegmenst bemásoljuk a pg_xlog mappába (a restore command biztosítja ennek a fáljnak a meglétét)
cp /uhu/pgsql8.2.3/wal/last/* /uhu/pgsql8.2.3/data/pg_xlog
- kitöröljük a recovery.conf fájlt
- újraindítjuk a PostgreSQL adatbázis szervert.
Fontos, hogy a mentést végző adatbázis szerver egynél többször ne legyen leállítva úgy, hogy nem érhető el számára a kért wal szegmens, mert az adatvesztéshez vezethet. (Ezt a logfájljában jelzi ilyen esetben.)