印刷用表示へ切り替え 通常表示へ切り替え 更新履歴を表示 更新履歴を隠す
Linux InnoDB が破損し MySQL 全体が不安定に

InnoDB が破損したので修復を試みたところ MySQL 全体が不安定になってしまった。そこから一部のデータを捨てて復旧に至る。

■ ■ ■

ことの起こり

このブログは Movable Type を管理システムとして使っていてデータベースは MySQL である。このブログサーバには,ネットワーク監視システム Zabbix も導入していてデータベースは MySQL である (nlog(n): Zabbix 2.0.1 のインストール)。つまり,MySQL には2つのデータベースが入っている。

Zabbix を一旦導入したものの,システム更新した時には再インストールせず,そのままにしてあった (nlog(n): サーバの OS を Vine Linux 4.2 から 6.2 へ更新)。そしてこの度,監視してグラフ化したいものが出てきたため,Zabbix を再インストールした。ところが動作がおかしい。データベースが破損しているようだった。そこで,mysqlcheck コマンドを使ってデータベースを修復したところ (MySQL :: MySQL 5.6 リファレンスマニュアル :: 4.5.3 mysqlcheck — テーブル保守プログラム),MySQL 全体が不安定になってしまい,Movable Type まで動作しなくなってしまったのである。

動作環境

動作環境は,Vine Linux 6.2, MySQL 5.1.73, mysqlcheck 2.5.0, Zabbix 2.0.9 である。

障害の現象

MySQL の症状としては,ソケット経由での接続ができないというものだった。データベースのあるサーバで mysql コマンドを入力すると次のメッセージが表示された。

# mysql
ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/var/lib/mysql/mysql.sock' (2)

しかし,少し待ってから再度 mysql コマンドを入力すると,今度は接続できるのである。接続できないときには /var/lib/mysql/mysql.sock が消えていて,少し待ってみるだけで自動的に復活する。つまり,mysql.sock が消えたり生成されたりを繰り返していた。ただし,mysqldump による Zabbix データベースのバックアップには必ず失敗していた。

# mysqldump zabbix > zabbix_backup.sql
mysqldump: Error 2013: Lost connection to MySQL server during query when dumping table `history` at row: 190428

ハードディスクが不調だったときに破損したのだと思われる (nlog(n): 自宅サーバのハードディスクが死にかけ)。

対処の方針

この現象に,どのように対処するのがよいのか。Zabbix データベースをバックアップしようとすると必ず同じ場所でエラーとなることから,Zabbix データベースに問題があることは確実である。一番簡単なのは Zabbix データベース全体を削除し,最初から登録しなおすことである。ただ,どうせ削除してなおるなら,その前にいろいろやってみてからでも遅くない。そこで,データベースの修復を試してみて,どうしようもなくなった時点で諦めて作りなおすということにした。

流れは次の通り。ここで扱うデータベースは Zabbix が使う innoDB のみである。Movable Type は対象外として特に何もしない。最後に動作確認をするくらいである。

  1. データベースを修復する
  2. データベースをバックアップする
  3. データベースを削除する
  4. innodb_file_per_table を有効にしてデータベースを再構築する
  5. バックアップからリストアする

InnoDB の修復

Zabbix が扱うデータベースエンジンは InnoDB である。InnoDB の修復をマニュアルに沿って行う (MySQL :: MySQL 5.6 リファレンスマニュアル :: 14.19.2 InnoDB のリカバリの強制的な実行)。

MySQL の設定ファイル /etc/my.cnf を編集して設定値を変えながらバックアップを試していく。

# vi /etc/my.cnf
[mysqld]
innodb_force_recovery = 1

設定値を変更したら,MySQL を再起動してバックアップを試す。

# /etc/init.d/mysql restart
# mysqldump zabbix > zabbix_backup.sql
mysqldump: Got error: 2013: Lost connection to MySQL server during query when using LOCK TABLES

innodb_force_recovery の値を 2, 3, 4 まで変えながら MySQL を再起動して試したが,バックアップはすべて失敗した。

# mysqldump zabbix > zabbix_backup.sql
mysqldump: Error 2013: Lost connection to MySQL server during query when dumping table `history` at row: 190428

少なくとも「history」テーブルに問題があるのは確実なようだ。そこで,このテーブルを削除することにした。

# mysql
mysql> use database zabbix;
mysql> drop history;
mysql> quit;

そして同じ手順でバックアップを試していく。

# vi /etc/my.cnf
[mysqld]
innodb_force_recovery = 1
# /etc/init.d/mysql restart
# mysqldump zabbix > zabbix_backup.sql
mysqldump: Got error: 2013: Lost connection to MySQL server during query when using LOCK TABLES

「innodb_force_recovery = 1」では失敗。そこで「innodb_force_recovery = 2」としたところ,

# vi /etc/my.cnf
[mysqld]
innodb_force_recovery = 2
# /etc/init.d/mysql restart
# mysqldump zabbix > zabbix_backup.sql
#

バックアップに成功した。

データベースの削除

Zabbix データベースをまるごと削除する。しかし,以下のように1回目は失敗し,続けて同じコマンドを入力すると2回目は成功した。

mysql> drop database zabbix;
No connection. Trying to reconnect...
ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/var/lib/mysql/mysql.sock' (2)
ERROR:
Can't connect to the server
mysql> drop database zabbix;
No connection. Trying to reconnect...
Connection id:    1
Current database: *** NONE ***
Query OK, 102 rows affected (3.51 sec)

MySQL サーバを止めて InnoDB 関連のファイルを削除 (戻せるように移動) する。削除対象は ib_logfile0, ib_logfile1, ibdata1, localhost.localdomain.err である。

# /etc/init.d/mysql stop
# mv /var/lib/mysql/ib_logfile* /tmp
# mv /var/lib/mysql/ibdata1 /tmp
# mv /var/lib/mysql/localhost.localdomain.err /tmp

innodb_file_per_table を有効にしてデータベースを再構築する

innodb_file_per_table を有効にすると,データベースの肥大化が防げるという。これはデータベースを構築する前に指定しておく必要がある。Zabbix データベースを削除した今,絶好の機会だと言える。データベースのバックアップは完了したので,innodb_force_recovery を無効にし,innodb_file_per_table を有効化する。

# vi /etc/my.cnf
[mysqld]
# innodb_force_recovery = 2
innodb_file_per_table

上の実行結果は,表記が分かりづらくなっている。vi の前の「#」は root のプロンプト,innodb_force_recovery = 2 の前の「#」は設定ファイル内のコメント記号である。

バックアップからのリストア

MySQL を起動し,バックアップした Zabbix のデータベースをリストアする。ただし,バックアップには history テーブルが削除されているため不完全であるので,リストアする前に Zabbix データベースを初期化再構築しておく必要がある (1 データベース作成スクリプト [Zabbix Documentation 2.0])。

# /etc/init.d/mysql start
# mysql -uzabbix -p<password>
mysql> create database zabbix character set utf8 collate utf8_bin;
mysql> quit;
# mysql -uzabbix -p<password> zabbix < database/mysql/schema.sql
# mysql -uzabbix -p<password> zabbix < database/mysql/images.sql
# mysql -uzabbix -p<password> zabbix < database/mysql/data.sql
# mysql -uzabbix -p<password> zabbix < zabbix_backup.sql

まとめ

MySQL に複数のデータベースがある場合,どれか1つのデータベースに問題があると MySQL 全体が不安定になることがある。mysqlcheck で修復すると障害がより深刻になることがある。

Posted by n at 2016-07-05 21:50 | Edit | Comments (0) | Trackback(0)
Trackbacks

  • 「手違いで複数トラックバックを送ってしまった!」という場合でも気にしないでください (重複分はこちらで勝手に削除させていただきます)
  • タイムアウトエラーは,こちらのサーバの処理能力不足が原因です (詳細は トラックバック送信時のエラー をご覧ください)
  • トラックバックする記事には,この記事へのリンクを含めてください(詳細は 迷惑トラックバック対策 をご覧ください)
Comments
Post a comment
  • 電子メールアドレスは必須ですが,表示されません (気になる場合は「メールアドレスのような」文字列でもOKです)
  • URL を入力した場合はリンクが張られます
  • コメント欄内ではタグは使えません
  • コメント欄内に URL を記入した場合は自動的にリンクに変換されます
  • コメント欄内の改行はそのまま改行となります
  • 「Confirmation Code」に表示されている数字を入力してください (迷惑コメント対策です)


(必須, 表示されます)


(必須, 表示されません)


(任意, リンクされます)


Confirmation Code (必須)


Remember info (R)?