IP.Board i uszkodzony index

Jest sobie forum postawione na IP.Board, który jest prawie idealny. Prawie, ponieważ używa mysql’a zamiast postgresql’q. Gdyby używał tego ostatniego były perfekcyjny.

Tabela posts używa inno db, o którym im więcej wiem, tym bardziej mam go dość. No ale wracając.

Z cron’a chodzą sobie backupy baz danych, między innymi mysqldump, który od kilku dni (niestety) wywalał się z następującym komunikatem:

mysqldump: Error 2013: Lost connection to MySQL server during query when dumping table `ibf_posts` at row: 111598
mysqldump: Got error: 2002: Can't connect to local MySQL server through socket

Co w logach widziane było tak: (zresztą select count(*) from ibf_posts, skutkowało tym samym błędem)

InnoDB: Page checksum 396689542, prior-to-4.0.14-form checksum 4074025863 stored checksum 4054066906, prior-to-4.0.14-form stored checksum 1768235130
Page may be an index page where index id is 0 6702
Database page corruption on disk or a failed file read of page 400.
You may have to recover from a backup.
It is also possible that your operating system has corrupted its own file cache and rebooting your computer removes the error.
If the corrupt page is an index page you can also try to fix the corruption by dumping, dropping, and reimporting the corrupt table. You can use CHECK TABLE to scan your table for corruption.
See also InnoDB: about forcing recovery.
Ending processing because of a corrupt database page.
Number of processes running now: 0
restarted

Strona polecana przez logi jest ok, poza tym, że procedura tam opisana do niczego nie prowadzi. Mimo:
InnoDB: !!! innodb_force_recovery is set to 4 !!!
Skończyło się propozycją wysłania stack trace’a, zgodnie zkolejną opisaną procedurą: http://dev.mysql.com/doc/mysql/en/using-stack-trace.html

Mam to w nosie.

A ponieważ cała baza i tak działa (aktualnie backupuje się co godzina katalog /var/lib/mysql i jest spokój.)

W sumie trzeba mi było od razu zastosować się do procedury opisanej na pierwszej polecanej stronie. Czyli skopiować dane, wywalić tabelę, założyć tabelę, przywrócić dane.

W sumie wygląda prosto, ale … nie miałem jak wykonać dumpa, co gorzej większość zapytań korzystających z całych kluczy wywalało się. Całe szczęście dało się wyciągnąć z całej tabeli pole pid, które jest kluczem głównym tej tabeli.

Mając to pole, mogłem wyciągnąć dane po kolei i zapisać je sobie na boczku, potem już łatwo: skasować tabelę, załadować (bez kluczy) wgrać dane i zapiąć klucze.

W czasie pracy powstały następujące pliki:

  • read.pl – czyta dane z bazy
  • write.pl – zapisuje do bazy dane z pliku
  • ifb_posts.sql – kasuje
  • ifb_posts_keys.sql

Które można sobie pobrać tutaj: ip.board.posts.tar.bz2

Na koniec warto wykonać:

OPTIMIZE TABLE ibf_posts;

Z ciekawostek w czasie pracy:

Dla niektórych zapytań pojawiał się następujący błąd: ERROR 1030 (HY000): Got error -1 from storage engine co doprowadziło do przeczytania wątku na stronie mysql’a: http://bugs.mysql.com/bug.php?id=30225 który mnie po prostu rozbawił, jako że nie uznano tego błędu za błąd, a receptą była aktualizacja. Słabo?