sql >> Databáze >  >> RDS >> Mysql

Replikace MySQL a selhání založené na GTID – hluboký ponor do chybných transakcí

Po celá léta byla replikace MySQL založena na binárních událostech protokolu - jediné, co slave věděl, byla přesná událost a přesná pozice, kterou právě načetl z mastera. Každá jednotlivá transakce z hlavního serveru mohla skončit v různých binárních protokolech a na různých pozicích v těchto protokolech. Bylo to jednoduché řešení s omezeními – složitější změny topologie mohly vyžadovat, aby správce zastavil replikaci na příslušných hostitelích. Nebo by tyto změny mohly způsobit nějaké další problémy, např. slave nebylo možné přesunout dolů v replikačním řetězci bez časově náročného procesu přestavby (nemohli jsme snadno změnit replikaci z A -> B -> C na A -> C -> B bez zastavení replikace na B i C). Všichni jsme museli obejít tato omezení, když jsme snili o globálním identifikátoru transakce.

GTID bylo představeno spolu s MySQL 5.6 a přineslo několik zásadních změn ve způsobu, jakým MySQL funguje. Za prvé, každá transakce má jedinečný identifikátor, který ji identifikuje stejným způsobem na každém serveru. Už není důležité, v jaké pozici binárního logu byla transakce zaznamenána, vše, co potřebujete znát, je GTID:‚966073f3-b6a4-11e4-af2c-080027880ca6:4‘. GTID se skládá ze dvou částí – jedinečného identifikátoru serveru, kde byla transakce poprvé provedena, a pořadového čísla. Ve výše uvedeném příkladu můžeme vidět, že transakci provedl server s server_uuid „966073f3-b6a4-11e4-af2c-080027880ca6“ a je to 4. transakce tam provedená. Tyto informace stačí k provedení komplexních změn topologie – MySQL ví, které transakce byly provedeny, a proto ví, které transakce je třeba provést jako další. Zapomeňte na binární protokoly, vše je v GTID.

Kde tedy můžete najít GTID? Najdete je na dvou místech. U slave v „zobrazit stav otroka“ najdete dva sloupce:Retrieved_Gtid_Set a Executed_Gtid_Set. První pokrývá GTID, která byla načtena z mastera prostřednictvím replikace, druhá informuje o všech transakcích, které byly na daném hostiteli provedeny – ať už prostřednictvím replikace, nebo provedeny lokálně.

Snadné nastavení replikačního clusteru

Nasazení replikačního clusteru MySQL je v ClusterControl velmi snadné (můžete si jej zdarma vyzkoušet). Jediným předpokladem je, že ke všem hostitelům, na které budete nasazovat MySQL uzly, lze přistupovat z instance ClusterControl pomocí připojení SSH bez hesla.

Když je připojení na místě, můžete nasadit cluster pomocí možnosti „Nasadit“. Když je otevřené okno průvodce, musíte udělat několik rozhodnutí – co chcete dělat? Nasadit nový cluster? Nasaďte uzel Postgresql nebo importujte existující cluster.

Chceme nasadit nový cluster. Poté se nám zobrazí následující obrazovka, na které se musíme rozhodnout, jaký typ clusteru chceme nasadit. Vybereme replikaci a poté předáme požadované podrobnosti o konektivitě ssh.

Až budete připraveni, klikněte na Pokračovat. Tentokrát se musíme rozhodnout, kterého dodavatele MySQL bychom chtěli použít, jakou verzi a několik konfiguračních nastavení včetně, mimo jiné, hesla pro účet root v MySQL.

Nakonec se musíme rozhodnout pro topologii replikace – můžete buď použít typické nastavení master – slave, nebo vytvořit složitější, aktivní – pohotovostní – master – master pár (+ slave, pokud je chcete přidat). Jakmile budete připraveni, klikněte na „Deploy“ a za pár minut byste měli mít cluster nasazený.

Jakmile to uděláte, uvidíte svůj cluster v seznamu clusterů uživatelského rozhraní ClusterControl.

Po spuštění replikace se můžeme blíže podívat na to, jak GTID funguje.

Chybné transakce – v čem je problém?

Jak jsme zmínili na začátku tohoto příspěvku, GTID přineslo významnou změnu ve způsobu, jakým by lidé měli přemýšlet o replikaci MySQL. Vše je o zvycích. Řekněme, že z nějakého důvodu aplikace provedla zápis na jednom z otroků. Nemělo se to stát, ale překvapivě se to děje pořád. V důsledku toho se replikace zastaví s chybou duplicitního klíče. Existuje několik způsobů, jak se s takovým problémem vypořádat. Jedním z nich by bylo odstranění problematického řádku a restartování replikace. Další možností je přeskočit událost binárního protokolu a restartovat replikaci.

STOP SLAVE SQL_THREAD; SET GLOBAL sql_slave_skip_counter =1; START SLAVE SQL_THREAD; 

Oba způsoby by měly vrátit replikaci zpět do práce, ale mohou způsobit posun dat, takže je nutné pamatovat na to, že po takové události by měla být zkontrolována konzistence slave zařízení (pt-table-checksum a pt-table-sync zde dobře fungují).

Pokud k podobnému problému dojde při používání GTID, zaznamenáte určité rozdíly. Může se zdát, že odstranění problematického řádku problém vyřeší, replikace by měla být schopna zahájit. Druhá metoda, pomocí sql_slave_skip_counter, nebude fungovat vůbec - vrátí chybu. Pamatujte, že to nyní není o událostech binlogu, ale o tom, zda je GTID spuštěno nebo ne.

Proč se smazáním řádku „zdá“ pouze vyřešení problému? Jedna z nejdůležitějších věcí, které je třeba mít na paměti ohledně GTID, je, že slave při připojení k masteru zkontroluje, zda nechybí nějaké transakce, které byly provedeny na masteru. Tyto transakce se nazývají chybné transakce. Pokud otrok takové transakce najde, provede je. Předpokládejme, že jsme spustili následující SQL, abychom vymazali problematický řádek:

DELETE FROM mytable WHERE id=100; 

Zkontrolujeme zobrazení stavu podřízeného:

master_uuid:966073f3-b6a4-11e4-af2c-080027880ca6 načteno_gtid_set:966073f3-b6a4-11e4-af2c-080027880Ca6:84dd15910-B6a4-11E4 -060104111115905060406060604060606010060060060060060060. 11e4-af2c-080027880ca6:1-29,

A podívejte se, odkud pochází 84d15910-b6a4-11e4-af2c-080027880ca6:1:

mysql> ZOBRAZIT PROMĚNNÉ JAKO 'server_uuid'\G******************************** 1. řádek **** *********************** Název_proměnné:server_uuid Hodnota:84d15910-b6a4-11e4-af2c-080027880ca61 řádek v sadě (0,00 s) 

Jak vidíte, máme 29 transakcí, které pocházejí z hlavního, UUID 966073f3-b6a4-11e4-af2c-080027880ca6 a jednu, která byla provedena lokálně. Řekněme, že v určitém okamžiku přepneme na selhání a hlavní (966073f3-b6a4-11e4-af2c-080027880ca6) se stane otrokem. Zkontroluje svůj seznam provedených GTID a nenajde toto:84d15910-b6a4-11e4-af2c-080027880ca6:1. V důsledku toho se provede související SQL:

DELETE FROM mytable WHERE id=100; 

To není něco, co jsme očekávali... Pokud by mezitím byl binlog obsahující tuto transakci vyčištěn na starém slave zařízení, pak si nový slave bude po převzetí služeb při selhání stěžovat:

 Last_IO_Error:Při čtení dat z binárního protokolu došlo od mastera k závažné chybě 1236:'Podřízená jednotka se připojuje pomocí CHANGE MASTER TO MASTER_AUTO_POSITION =1, ale master vyčistil binární protokoly obsahující GTID, které slave vyžaduje.' 

Jak odhalit chybné transakce?

MySQL poskytuje dvě funkce, které se velmi hodí, když chcete porovnat sady GTID na různých hostitelích.

GTID_SUBSET() vezme dvě sady GTID a zkontroluje, zda je první sada podmnožinou druhé.

Řekněme, že máme následující stav.

Mistr:

mysql> zobrazit hlavní stav\G*************************** 1. řádek ******** ******************** Soubor:binlog.000002 Pozice:160205927 Binlog_Do_DB:Binlog_Ignore_DB:Executed_Gtid_Set:8a6962d2-b907-11e4-bebc-080027815b39,44 b907-11e4-bebd-080027880ca6:1,ab8f5793-b907-11e4-bebd-080027880ca6:1-21 řádek v sadě (0,00 s) 

Slave:

mysql> zobrazit stav otroka\G[...] Retrieved_Gtid_Set:8a6962d2-b907-11e4-bebc-080027880ca6:1-153,9b09b44a-b907-11e4-becut27886 -11e4-bebc-080027880ca6:1-153,9b09b44a-b907-11e4-bebd-080027880ca6:1,ab8f5793-b907-11e4-bebd-086002784 

Můžeme zkontrolovat, zda má slave nějaké chybné transakce provedením následujícího SQL:

mysql> SELECT GTID_SUBSET('8a6962d2-b907-11e4-bebc-080027880ca6:1-153,ab8f5793-b907-11e4-bebd-080027880,9be6:7d-21222 080027880ca6:1-153, 9b09b44a-b907-11e4-bebd-080027880ca6:1, ab8f5793-b907-11e4-bebd-080027880ca6:1_7880ca6:1_subset****\****\subset ************** 1. řádek ********************************je_podmnožina:01 řádek v sadě (0,00 s) 

Zdá se, že existují chybné transakce. Jak je poznáme? Můžeme použít jinou funkci, GTID_SUBTRACT()

mysql> SELECT GTID_SUBTRACT('8a6962d2-b907-11e4-bebc-080027880ca6:1-153,ab8f5793-b907-11e4-bebd-080027880ca6:81-220ca6:81-22 080027880ca6:1-153, 9b09b44a-b907-11e4-bebd-080027880ca6:1, ab8f5793-b907-11e4-bebd-080027880ca6:1-2G') ************** 1. řádek ****************************chybí:ab8f5793-b907- 11e4-bebd-080027880ca6:3-41 řádek v sadě (0,01 s) 

Naše chybějící GTID jsou ab8f5793-b907-11e4-bebd-080027880ca6:3-4 – tyto transakce byly provedeny na podřízeném, ale ne na hlavním.

Jak vyřešit problémy způsobené chybnými transakcemi?

Existují dva způsoby – vložení prázdných transakcí nebo vyloučení transakcí z historie GTID.

Pro vložení prázdných transakcí můžeme použít následující SQL:

mysql> SET gtid_next='ab8f5793-b907-11e4-bebd-080027880ca6:3';Dotaz je v pořádku, ovlivněno 0 řádků (0,01 s) 
mysql> begin; commit;Dotaz je v pořádku, ovlivněno 0 řádků (0,00 s) Dotaz je v pořádku, ovlivněno 0 řádků (0,01 s) 
mysql> SET gtid_next='ab8f5793-b907-11e4-bebd-080027880ca6:4';Dotaz je v pořádku, ovlivněno 0 řádků (0,00 s) 
mysql> begin; commit;Dotaz OK, ovlivněno 0 řádků (0,00 s)Dotaz OK, ovlivněno 0 řádků (0,01 s) 
mysql> SET gtid_next=automatic;Dotaz je v pořádku, ovlivněno 0 řádků (0,00 s) 

Toto musí být provedeno na každém hostiteli v topologii replikace, který nemá tato GTID spuštěna. Pokud je hlavní server k dispozici, můžete tam tyto transakce vložit a nechat je replikovat v řetězci. Pokud master není dostupný (například se zhroutil), musí být tyto prázdné transakce provedeny na každém slave. Oracle vyvinul nástroj nazvaný mysqlslavetrx, který je určen k automatizaci tohoto procesu.

Dalším přístupem je odstranění GTID z historie:

Stop slave:

mysql> STOP SLAVE; 

Vytisknout Executed_Gtid_Set na slave:

mysql> ZOBRAZIT STAV MASTER\G 

Resetovat informace GTID:

RESET MASTER; 

Nastavte GTID_PURGED na správnou sadu GTID. na základě údajů z SHOW MASTER STATUS. Ze sady byste měli vyloučit chybné transakce.

SET GLOBAL GTID_PURGED='8a6962d2-b907-11e4-bebc-080027880ca6:1-153, 9b09b44a-b907-11e4-bebd-080027880 ab83-119080caf-29007017017007109007017007070707070707909:209909:2099077079:20900 '; 

Start slave.

mysql> START SLAVE\G 

V každém případě byste měli ověřit konzistenci svých otroků pomocí pt-table-checksum a pt-table-sync (je-li potřeba) – chybná transakce může vést k posunu dat.

Failover v ClusterControl

Počínaje verzí 1.4 ClusterControl vylepšil své procesy zpracování selhání pro replikaci MySQL. Stále můžete provést ruční hlavní přepnutí povýšením jednoho z podřízených na hlavní. Zbytek otroků pak přejde na nového mastera. Od verze 1.4 má ClusterControl také schopnost provádět plně automatizované převzetí služeb při selhání v případě selhání hlavního serveru. Podrobně jsme to probrali v blogovém příspěvku popisujícím ClusterControl a automatické převzetí služeb při selhání. Ještě bychom rádi zmínili jednu funkci, která přímo souvisí s tématem tohoto příspěvku.

Ve výchozím nastavení ClusterControl provádí převzetí služeb při selhání „bezpečným způsobem“ – v době převzetí služeb při selhání (nebo přepnutí, pokud je to uživatel, který provedl hlavní přepínač), ClusterControl vybere hlavního kandidáta a poté ověří, že tento uzel nemá žádné chybné transakce. což by ovlivnilo replikaci, jakmile bude povýšena na hlavní. Pokud je zjištěna chybná transakce, ClusterControl zastaví proces převzetí služeb při selhání a hlavní kandidát nebude povýšen na nového hlavního.

Pokud si chcete být 100% jisti, že ClusterControl bude podporovat nový master, i když budou zjištěny nějaké problémy (jako chybné transakce), můžete to udělat pomocí nastavení replikace_stop_on_error=0 v konfiguraci cmon. Samozřejmě, jak jsme diskutovali, může to vést k problémům s replikací - slave mohou začít žádat o binární log událost, která již není dostupná.

Abychom takové případy zvládli, přidali jsme experimentální podporu pro přestavbu otroka. Pokud nastavíte replication_auto_rebuild_slave=1 v konfiguraci cmon a váš slave je označen jako nefunkční s následující chybou v MySQL, ClusterControl se pokusí znovu sestavit slave zařízení pomocí dat z master:

Dostala závažná chyba 1236 z masteru při čtení dat z binárního protokolu:'Slave se připojuje pomocí CHANGE MASTER TO MASTER_AUTO_POSITION =1, ale master vyčistil binární protokoly obsahující GTID, které slave vyžaduje.'

Takové nastavení nemusí být vždy vhodné, protože proces přestavby způsobí zvýšené zatížení masteru. Může se také stát, že vaše datová sada je velmi velká a pravidelná přestavba nepřipadá v úvahu – proto je toto chování ve výchozím nastavení zakázáno.


  1. Připojení k MySQL z Androidu pomocí JDBC

  2. Oracle:Fulltextové vyhledávání s podmínkou

  3. Jak povolit pomalé dotazy MySQL Přihlaste se do MySQL

  4. Jak zobrazit skutečný příkaz Oracle SQL, který se provádí