it-swarm-eu.dev

Nalezení a oprava poškození InnoDB indexu

Včera jsem narazil na nový problém s jednou z mých MySQL 5.5 slave DB, která běží na EC2 v AWS. DB byla vytvořena ze snímku jiného otroka. Data jsou správná, ale pro alespoň jednu tabulku sekundární index vrací neúplné výsledky. Dotaz na podřízenou tabulku nadřazeným id vrátil 498 řádků, když měl vrátit 504. Dotaz na chybějících 6 řádků primárním klíčem pracoval a byl vrácen správný nadřazený id, takže problém je se sekundárním indexem.

Tento problém se mě velmi týká, protože pravděpodobně i když všechna data na slave odpovídají hlavnímu, stále dostanu nesprávné výsledky z některých dotazů spuštěných na slave.

Mým řešením s hrubou silou bylo přestavět celý stůl takto:

alter table my_table engine = innodb;

To vyřešilo problém této konkrétní tabulky, ale zbývají mi následující otázky:

1) How can I determine if other tables have similar index corruption?
2) What's the most efficient way to fix the corrupt indexes?

Našel jsem nějaké dobré zdroje online pro nalezení a opravu poškození dat InnoDB, ale nenašel jsem nic důležitého pro poškození indexu InnoDB.

Podíval jsem se do protokolu chyb MySQL a nenašel jsem kouřící zbraň. Našel jsem nějaké znepokojující chyby InnoDB. Předpokládám, že se jedná o samostatný problém, ale může to souviset:

130109  9:46:41  InnoDB: unable to find a record to delete-mark
InnoDB: Tuple DATA Tuple: 2 fields;
 0: len 4; hex 04af1f21; asc    !;;
 1: len 4; hex 0a1c03bd; asc     ;;

InnoDB: record PHYSICAL RECORD: n_fields 2; compact format; info bits 0
 0: len 4; hex 04af1f21; asc    !;;
 1: len 4; hex 0a052a77; asc   *w;;
7
Ike Walker

Děkujeme Rolandovi a Michaelovi za vaše odpovědi.

Abych smyčku uzavřel, odpovím na své původní otázky:

  • Otázka: Jak zjistím, zda jiné tabulky mají podobné poškození indexu?
  • A: Použijte CHECK TABLE. Běžel jsem mysqlcheck -c na všech příslušných tabulkách InnoDB, abyste zjistili, které z nich měly poškození index

  • Otázka: Jaký je nejúčinnější způsob, jak opravit poškozené indexy?

  • A: Použijte OPTIMIZE TABLE znovu sestavit tabulku InnoDB, která má poškozené indexy. To způsobí kompletní sestavení tabulky, které opraví poškození.
14
Ike Walker

Možná máte nejjednodušší řešení. Rád bych však objasnil některé věci:

Vytvoření snímku se spuštěnou instancí MySQL by mohlo ovlivnit jeden soubor, který je odpovědný za manipulaci se sekundárním indexem: ibdata1.

Systémový tabulkový prostor ibdata1 je domovem 7 tříd informací InnoDB

  • Datové stránky (pokud je innodb_file_per_table zakázáno)
  • Indexové stránky (pokud je zakázáno innodb_file_per_table)
  • Datový slovník (zahrnutý seznam tabulek a jejich ID TableSpace)
  • Vyrovnávací paměť s dvojitým zápisem (poskytuje informace o kontrolním součtu, aby se zabránilo poškození dat)
  • Vložit vyrovnávací paměť (změny sekundárních indexů)
  • Opakujte protokoly
  • Zrušit protokoly
  • Obrazová reprezentace

Klíčové třídy, o které bych se bál, jsou vyrovnávací paměť Double Write a Insert Buffer. Pokud provedete živý snímek s některým z těchto nesprávně napsaných, dojde k poškození dat.

Děláme FLUSH TABLES WITH READ LOCK; nezastaví zápisy do ibdata1, jak by si člověk myslel. O tomto tématu jsem psal dříve . Dřív jsem si myslel, že ano, dokud se o tom nezmínil kolega člena DBA.SE @ShlomiNoach .

Přemýšlejte o fondu vyrovnávacích pamětí InnoDB. Budete muset vyprázdnit každou špinavou stránku, abyste dostali vše na disk. Následující vynutí všechny špinavé stránky na základě tabulky:

  • SET GLOBAL innodb_fast_shutdown = 0; následován service mysql stop
  • SET GLOBAL innodb_max_dirty_pages_pct = 0; a počkejte, dokud nebude znečištěno 1% fondu vyrovnávacích pamětí
  • mysqldump

Nezapomeňte také, že binární protokoly a protokoly relé závisí na operačním systému pro splachování.

Snímek EC2 není MySQL-Aware v tomto ohledu, nic víc než snímek LVM. To je důvod, proč záložní software, jako je CDP R1Soft, má MySQL modul pro takové příležitosti.

Naproti tomu je instance Amazon RDS MYSQL vědoma a vytvořena pro takové scénáře zaměřené na InnoDb. Pouze pokud existují aktivní tabulky MyISAM v instanci RDS, FLUSH TABLES WITH READ LOCK; být nezbytné zlo pro ruční provedení .

Pokud jde o vaši původní otázku, když jste běželi ALTER TABLE my_table ENGINE=InnoDB; jednoduše obnovíte čtení indexových stránek z datových stránek tabulky, s největší pravděpodobností obejít ibdata1 Insert Buffer. Proto to pro vás fungovalo.

Pokud můžete udělat mysqldump s --single-transaction --master-data=1 na Mistře, pošlete MySQL do otroka a udělejte to bez finančních poplatků, což by byla bezpečnější metoda pro nastavení EC2 Slave.

Pokud musíte udělat snímek, udělejte to na Slave:

  • Spustit SET GLOBAL innodb_fast_shutdown = 0;
  • service mysql stop
  • Proveďte snímek
  • service mysql start
  • Přidat innodb_fast_shutdown do /etc/my.cnf

Další informace: Čím menší ib_logilfe0 a ib_logfile1 jsou, tím rychlejší je vypnutí.

Doufám, že to hodně vysvětluje.

AKTUALIZACE 2013-01-14 10:36 EDT

Nedávno jste se zeptali v sekci komentářů

jak zjistím, zda má databáze poškození indexu?

Mějte na paměti, že používáte EC2 a ne RDS. S RDS je Amazon zodpovědný za holistický stav VM a MySQL Instance). U EC2 je Amazon zodpovědný pouze zaVM). MySQL instance nyní leží na vás. Možná budete chtít přenést databázi do RDS, protože přichází s dalšími zvonky a píšťalky, které chrání před takovým poškozením.

8
RolandoMySQLDBA