Zálohy jsou zásadní, pokud jde o bezpečnost dat. Jsou dokonalým řešením pro obnovu po havárii – nemáte dosažitelné žádné databázové uzly a vaše datové centrum by mohlo doslova vyhořet, ale pokud máte zálohu svých dat, můžete se z takové situace stále zotavit.
Obvykle budete používat zálohy k obnově z různých typů případů:
- náhodné DROP TABLE nebo DELETE bez klauzule WHERE nebo s klauzulí WHERE, která nebyla dostatečně konkrétní.
- upgrade databáze, který selže a poškodí data
- selhání/poškození úložného média
Obnovení ze zálohy nestačí? Co to musí být point-in-time? Musíme mít na paměti, že záloha je snímek dat pořízený v daném okamžiku. Pokud provedete zálohu v 1:00 a stůl byl omylem odstraněn v 11:00, můžete svá data obnovit až do 1:00, ale co změny, ke kterým došlo mezi 1:00 a 11:00? Tyto změny by byly ztraceny, pokud nemůžete znovu přehrát úpravy, ke kterým došlo mezitím. Naštěstí má MySQL takový mechanismus pro ukládání změn – binární logy. Možná víte, že tyto protokoly se používají pro replikaci – MySQL je používá k ukládání všech změn, které se staly na hlavním serveru, a podřízený server je používá k přehrání těchto změn a jejich aplikaci na svou datovou sadu. Protože binlogy ukládají všechny změny, můžete je také použít k přehrání provozu. V tomto příspěvku na blogu se podíváme na to, jak vám ClusterControl může pomoci provést Point-In-Time Recovery (PITR).
Vytvoření zálohy kompatibilní s obnovou bodu v čase
Nejprve si promluvme o předpokladech. Hostitel, ze kterého provádíte zálohy, musí mít povoleny binární protokoly. Bez nich není PITR možný. Druhý požadavek - hostitel, ze kterého provádíte zálohy, by měl mít všechny binární protokoly potřebné k obnovení do daného okamžiku. Pokud používáte příliš agresivní rotaci binárních protokolů, může to být problém.
Pojďme se tedy podívat, jak tuto funkci používat v ClusterControl. Nejprve si musíte udělat zálohu, která je kompatibilní s PITR. Taková záloha musí být úplná, úplná a konzistentní. Pro xtrabackup platí, že pokud obsahuje úplnou datovou sadu (nezahrnuli jste pouze podmnožinu schémat), bude kompatibilní s PITR.
Pro mysqldump existuje možnost, aby byl kompatibilní s PITR. Když tuto možnost povolíte, všechny potřebné možnosti budou nakonfigurovány (například nebudete moci vybrat samostatná schémata, která se mají zahrnout do výpisu) a záloha bude označena jako dostupná pro obnovení v určitém okamžiku.
Obnova bodu v čase ze zálohy
Nejprve musíte vybrat zálohu, kterou chcete obnovit.
Pokud je záloha kompatibilní s PITR, zobrazí se možnost provést obnovu v určitém okamžiku. K tomu budete mít dvě možnosti – „Na základě času“ a „Na základě pozice“. Pojďme diskutovat o rozdílu mezi těmito dvěma možnostmi.
„Časově založený“ PITR
Pomocí této možnosti můžete zadat datum a čas, do kterého má být záloha obnovena. Lze jej definovat s rozlišením jedné sekundy. Nezaručuje, že všechna data budou obnovena, protože i když jste velmi přesní v definování času, během jedné sekundy by mohlo být zaznamenáno více událostí do binárního protokolu. Řekněme, že víte, že ke ztrátě dat došlo 18. dubna v 10:00:01. Do formuláře zadáte následující datum a čas:‚2018-04-18 10:00:00‘. Mějte prosím na paměti, že byste měli používat čas, který je založen na nastavení časového pásma na databázovém serveru, na kterém byla záloha vytvořena.
Stále se může stát, že ztráta dat dokonce nebyla první, ke které došlo v 10:00:01, takže některé události budou během procesu ztraceny. Podívejme se, co to znamená.
Během jedné sekundy může být do binlogů zaznamenáno více událostí. Uvažujme takový případ:
10:00:00 - události A,B,C,D,E,F
10:00:01 - události V,W,X,Y,Z
kde X je událost ztráty dat. S přesností na sekundu můžete buď obnovit vše, co se stalo v 10:00:00 (tedy až do F) nebo až do 10:00:01 (až do Z). Poslední případ je k ničemu, protože X by bylo znovu spuštěno. V prvním případě nám chybí V a W.
Proto je obnova na základě polohy přesnější. Můžete říct "Chci obnovit až W".
Obnovení na základě času je nejpřesnější, jakého můžete dosáhnout, aniž byste museli přecházet do binárních protokolů a definovat přesnou pozici, kam chcete obnovit. To nás vede k druhé metodě provádění PITR.
PITR „Na základě pozice“
Zde jsou vyžadovány určité zkušenosti s nástroji příkazového řádku pro MySQL, konkrétně s nástrojem mysqlbinlog. Na druhou stranu budete mít nejlepší kontrolu nad tím, jak bude obnova provedena.
Pojďme si projít jednoduchý příklad. Jak můžete vidět na snímku obrazovky výše, budete muset předat název binárního protokolu a pozici binárního protokolu, do které má být záloha obnovena. Většinou by to měla být poslední pozice před událostí ztráty dat.
Někdo provedl příkaz SQL, který měl za následek vážnou ztrátu dat:
mysql> DROP TABLE sbtest1;
Query OK, 0 rows affected (0.02 sec)
Naše aplikace si okamžitě začala stěžovat:
sysbench 1.1.0-ecf1191 (using bundled LuaJIT 2.1.0-beta3)
Running the test with following options:
Number of threads: 2
Report intermediate results every 1 second(s)
Initializing random number generator from current time
Initializing worker threads...
Threads started!
FATAL: mysql_drv_query() returned error 1146 (Table 'sbtest.sbtest1' doesn't exist) for query 'DELETE FROM sbtest1 WHERE id=5038'
FATAL: `thread_run' function failed: /usr/local/share/sysbench/oltp_common.lua:490: SQL error, errno = 1146, state = '42S02': Table 'sbtest.sbtest1' doesn't exist
Máme zálohu, ale chceme obnovit všechna data až do toho osudného okamžiku. Za prvé předpokládáme, že aplikace nefunguje, takže všechny zápisy, které se staly po DROP TABLE, můžeme zahodit jako nedůležité. Pokud vaše aplikace do určité míry funguje, budete muset zbývající změny později sloučit. Dobře, podívejme se na binární protokoly, abychom našli pozici příkazu DROP TABLE. Protože se chceme vyhnout analýze všech binárních protokolů, pojďme zjistit, jakou pozici pokrývala naše nejnovější záloha. Můžete to zkontrolovat tak, že prozkoumáte protokoly pro nejnovější sadu záloh a vyhledejte řádek podobný tomuto:
Mluvíme tedy o názvu souboru 'binlog.000008' a pozici '16184120'. Použijme to jako výchozí bod. Podívejme se, jaké binární soubory protokolu máme:
[email protected]:~# ls -alh /var/lib/mysql/binlog.*
-rw-r----- 1 mysql mysql 58M Apr 17 08:31 /var/lib/mysql/binlog.000001
-rw-r----- 1 mysql mysql 116M Apr 17 08:59 /var/lib/mysql/binlog.000002
-rw-r----- 1 mysql mysql 379M Apr 17 09:30 /var/lib/mysql/binlog.000003
-rw-r----- 1 mysql mysql 344M Apr 17 10:54 /var/lib/mysql/binlog.000004
-rw-r----- 1 mysql mysql 892K Apr 17 10:56 /var/lib/mysql/binlog.000005
-rw-r----- 1 mysql mysql 74M Apr 17 11:03 /var/lib/mysql/binlog.000006
-rw-r----- 1 mysql mysql 5.2M Apr 17 11:06 /var/lib/mysql/binlog.000007
-rw-r----- 1 mysql mysql 21M Apr 18 11:35 /var/lib/mysql/binlog.000008
-rw-r----- 1 mysql mysql 59K Apr 18 11:35 /var/lib/mysql/binlog.000009
-rw-r----- 1 mysql mysql 144 Apr 18 11:35 /var/lib/mysql/binlog.index
Takže kromě 'binlog.000008' máme k prozkoumání také 'binlog.000009'. Spusťte příkaz, který převede binární protokoly do formátu SQL počínaje pozicí, kterou jsme našli v protokolu zálohování:
[email protected]:~# mysqlbinlog --start-position='16184120' --verbose /var/lib/mysql/binlog.000008 /var/lib/mysql/binlog.000009 > binlog.out
K dekódování událostí založených na řádcích je vyžadován uzel „--verbose“. To není nezbytně nutné pro DROP TABLE, který hledáme, ale pro jiné typy událostí to může být potřeba.
Pojďme v našem výstupu vyhledat dotaz DROP TABLE:
[email protected]:~# grep -B 7 -A 1 "DROP TABLE" binlog.out
# at 20885489
#180418 11:24:32 server id 1 end_log_pos 20885554 CRC32 0xb89f2e66 GTID last_committed=38168 sequence_number=38170 rbr_only=no
SET @@SESSION.GTID_NEXT= '7fe29cb7-422f-11e8-b48d-0800274b240e:38170'/*!*/;
# at 20885554
#180418 11:24:32 server id 1 end_log_pos 20885678 CRC32 0xb38a427b Query thread_id=54 exec_time=0 error_code=0
use `sbtest`/*!*/;
SET TIMESTAMP=1524050672/*!*/;
DROP TABLE `sbtest1` /* generated by server */
/*!*/;
V této ukázce můžeme vidět dvě události. Nejprve na pozici 20885489 nastaví proměnnou GTID_NEXT.
# at 20885489
#180418 11:24:32 server id 1 end_log_pos 20885554 CRC32 0xb89f2e66 GTID last_committed=38168 sequence_number=38170 rbr_only=no
SET @@SESSION.GTID_NEXT= '7fe29cb7-422f-11e8-b48d-0800274b240e:38170'/*!*/;
Za druhé, na pozici 20885554 je naše akce DROP TABLE. To vede k závěru, že bychom měli provést PITR až do pozice 20885489. Jedinou otázkou, kterou je třeba zodpovědět, je, o kterém binárním logu mluvíme. Můžeme to zkontrolovat vyhledáním položek rotace binlogu:
[email protected]:~# grep "Rotate to binlog" binlog.out
#180418 11:35:46 server id 1 end_log_pos 21013114 CRC32 0x2772cc18 Rotate to binlog.000009 pos: 4
Jak je jasně vidět z porovnání dat, k rotaci na binlog.000009 došlo později, proto chceme ve formuláři předat binlog.000008 jako soubor binlog.
Dále se musíme rozhodnout, zda hodláme obnovit zálohu na clusteru, nebo chceme k obnově použít externí server. Tato druhá možnost může být užitečná, pokud chcete obnovit pouze podmnožinu dat. Můžete obnovit plnou fyzickou zálohu na samostatném hostiteli a poté pomocí mysqldump vypsat chybějící data a načíst je na produkční server.
Mějte na paměti, že když obnovíte zálohu v clusteru, budete muset znovu vytvořit uzly jiné než ten, který jste obnovili. Ve scénáři master - slave budete obvykle chtít obnovit zálohu na masteru a poté z něj znovu sestavit slave.
Jako poslední krok uvidíte souhrn akcí, které ClusterControl provede.
Nakonec po obnovení zálohy otestujeme, zda byla chybějící tabulka obnovena nebo ne:
mysql> show tables from sbtest like 'sbtest1'\G
*************************** 1. row ***************************
Tables_in_sbtest (sbtest1): sbtest1
1 row in set (0.00 sec)
Vše se zdá být v pořádku, podařilo se nám obnovit chybějící data.
Poslední krok, který musíme udělat, je přestavět našeho otroka. Upozorňujeme, že existuje možnost použití zálohy PITR. V tomto příkladu to není možné, protože slave by replikoval událost DROP TABLE a ta by nakonec nebyla konzistentní s masterem.