ITの隊長のブログ

ITの隊長のブログです。Rubyを使って仕事しています。最近も色々やっているお(^ω^ = ^ω^)

MySQLで破損していたテーブルを復旧した件

WordPressにログインしようとアクセスしたら、摩訶不思議エラーが発生。と、会社の人たちから連絡。

mysql_query() unable to save result set

↑のエラーで検索すると、よくあるのはMySQLからの結果をPHPが受け取れないエラーが多いらしいが、今回はそうじゃないっぽい・・・?

windowsos -> macosへデータ移行

エラーが発生したのはWindowsOSでした。コマンドラインでの復旧方法しか知らなかったので、mysqlのデータベースディレクトリをコピーしてmacへ送信。

mac側のmysqlディレクトリに追加して、mysqlコマンドラインで確認してみました。

macのosやmysqlのバージョンはこちら

$ sw_vers
ProductName:  Mac OS X
ProductVersion: 10.11.5
BuildVersion: 15F34

$ mysql -u root -p -D mysql -e "select version()"
Enter password: 
+-----------+
| version() |
+-----------+
| 5.7.13    |
+-----------+

-- wordpressは壊れたテーブルがあるデータベース名
$ show table status from wordpress
-- 色々省略したけど、table型はMyISAMでした
$ sudo cd /usr/local/var/mysql/
$ sudo unzip ~/Downloads/wordpress.zip
$ chown -R _mysql:_mysql wordpress

これで配置はおk

check table コマンド

check tableのコマンドは、複数テーブルのエラーがないかどうかをチェックするコマンドです。

また、table型によっては使えるオプションと使えないオプションがあるっぽいね

意味
QUICK 正しくないリンクをチェックするための行のスキャンを行いません。InnoDB および MyISAM テーブルとビューに適用されます。
FAST 正しく閉じられていないテーブルのみを検査します。MyISAM テーブルとビューにのみ適用されます。InnoDB では無視されます。
CHANGED 最後のチェック以降に変更されたか、または正しく閉じられていないテーブルのみをチェックします。MyISAM テーブルとビューにのみ適用されます。InnoDB では無視されます。
MEDIUM 削除されたリンクが有効であることを検証するために行をスキャンします。また、行のキーチェックサムも計算し、キーの計算されたチェックサムを使用してこれを検証します。MyISAM テーブルとビューにのみ適用されます。InnoDB では無視されます。
EXTENDED 行ごとにすべてのキーの完全なキールックアップを実行します。これにより、テーブルの 100% の整合性が保証されますが、長い時間がかかります。MyISAM テーブルとビューにのみ適用されます。InnoDB では無視されます。

今回はMEDIUMを使いました。

オプションについての利用用途はまだよくわかっていませんが、検索したらなんかMEDIUM使っている人多かったので。。。

http://www.freeml.com/bl/6236480/84512/

とりあえずデータベースにログインしてから実行してみる。

mysql> check table wp_options medium;
+----------------------+-------+----------+-----------------------------------------------------------+
| Table                | Op    | Msg_type | Msg_text                                                  |
+----------------------+-------+----------+-----------------------------------------------------------+
| wordpress.wp_options | check | warning  | Table is marked as crashed                                |
| wordpress.wp_options | check | warning  | 10 clients are using or haven't closed the table properly |
| wordpress.wp_options | check | error    | Found 175 keys of 174                                     |
| wordpress.wp_options | check | error    | Corrupt                                                   |
+----------------------+-------+----------+-----------------------------------------------------------+
4 rows in set (0.00 sec)

うぬぬ。。。やっぱりなんかぶっ壊れているっぽいぞ。

repair table コマンド

repair tableコマンドは特定のステレートエンジンに対してのみ、破損している可能性のあるテーブルを修復してくれるとのこと。

InnoDBは対応していないっぽい。。。。。個人的にはそっちを多く使うんですけど。。。

オプションが色々ありますが、USE_FRMを使いました。

USE_FRM オプションは、.MYI インデックスファイルがない場合や、そのヘッダーが破損している場合に使用できます。このオプションは MySQL に、.MYI ファイルヘッダー内の情報を信頼せずに、.frm ファイルからの情報を使用してファイルヘッダーを再作成するよう指示します。この種類の修復は、myisamchk では実行できません。

https://dev.mysql.com/doc/refman/5.6/ja/repair-table.html

mysql> repair table wp_options USE_FRM;
+----------------------+--------+----------+------------------------------------------------------+
| Table                | Op     | Msg_type | Msg_text                                             |
+----------------------+--------+----------+------------------------------------------------------+
| wordpress.wp_options | repair | info     | Delete link points outside datafile at 349632        |
| wordpress.wp_options | repair | info     | Delete link points outside datafile at 423104        |
| wordpress.wp_options | repair | info     | Found block that points outside data file at 424072  |
| wordpress.wp_options | repair | info     | Found block that points outside data file at 424176  |
| wordpress.wp_options | repair | info     | Found block that points outside data file at 424724  |
| wordpress.wp_options | repair | info     | Delete link points outside datafile at 436636        |
| wordpress.wp_options | repair | info     | Found block that points outside data file at 436744  |
| wordpress.wp_options | repair | info     | Found block with too small length at 437668; Skipped |
| wordpress.wp_options | repair | info     | Found block that points outside data file at 437980  |
| wordpress.wp_options | repair | info     | Found block that points outside data file at 438052  |
| wordpress.wp_options | repair | info     | Found block that points outside data file at 438236  |
| wordpress.wp_options | repair | warning  | Number of rows changed from 0 to 173                 |
| wordpress.wp_options | repair | status   | OK                                                   |
+----------------------+--------+----------+------------------------------------------------------+
13 rows in set (0.04 sec)

おおー。

もっかいcheck tableを実行してみる。

mysql> check table wp_options medium;
+----------------------+-------+----------+----------+
| Table                | Op    | Msg_type | Msg_text |
+----------------------+-------+----------+----------+
| wordpress.wp_options | check | status   | OK       |
+----------------------+-------+----------+----------+
1 row in set (0.01 sec)

おおぉー!

これでよし。

この流れを全テーブルに実行してみました。

特定のファイルが見つからなくて、repairできなかった時

1つだけおかしなテーブルが。。。

mysql> check table wp_usermeta medium;
+-----------------------+-------+----------+----------------------------------------------------------+
| Table                 | Op    | Msg_type | Msg_text                                                 |
+-----------------------+-------+----------+----------------------------------------------------------+
| wordpress.wp_usermeta | check | warning  | 9 clients are using or haven't closed the table properly |
| wordpress.wp_usermeta | check | status   | OK                                                       |
+-----------------------+-------+----------+----------------------------------------------------------+
2 rows in set (0.00 sec)

mysql> repair table wp_usermeta USE_FRM;
+-----------------------+--------+----------+------------------+
| Table                 | Op     | Msg_type | Msg_text         |
+-----------------------+--------+----------+------------------+
| wordpress.wp_usermeta | repair | Warning  | Can't open table |
| wordpress.wp_usermeta | repair | status   | Operation failed |
+-----------------------+--------+----------+------------------+
2 rows in set (0.00 sec)

mysql> repair table wp_usermeta USE_FRM;
+-------------+--------+----------+----------------------------------------+
| Table       | Op     | Msg_type | Msg_text                               |
+-------------+--------+----------+----------------------------------------+
| wp_usermeta | repair | error    | Failed generating table from .frm file |
+-------------+--------+----------+----------------------------------------+
1 row in set, 2 warnings (0.01 sec)

なおんぇええええ!!!

しかもなぜかエラーの返事もかわった(´;ω;`)ブワッ

怖い

でもメッセージみたら、「.frmがないお」みたいなエラーですね。

そんなばかな。

シェルのコンソールに戻り、ファイルを確認してみる。

$ sudo ls -l wp_usermeta*
-rw-r--r--  1 _mysql  _mysql  3656  7 22 10:02 wp_usermeta.MYD-81bc_16
-rw-r--r--  1 _mysql  _mysql  9216  7 21 22:49 wp_usermeta.MYI
-rw-r--r--  1 _mysql  _mysql  8684  7 22 09:55 wp_usermeta.frm

え・・・・?

wp_usermeta.MYD-81bc_16 <= なにこれ?

よくわからないけど、復旧の途中でミスった・・・・?

わからないけど、復旧させてみる。

とりあえず、元に戻す。

$ sudo cp wp_usermeta.MYD-81bc_16 wp_usermeta.MYD
$ sudo chown _mysql:_mysql wp_usermeta.MYD
$ ls -l wp_usermeta*
-rw-r--r--  1 _mysql  _mysql  3656  7 22 10:02 wp_usermeta.MYD
-rw-r--r--  1 _mysql  _mysql  3656  7 22 10:02 wp_usermeta.MYD-81bc_16
-rw-r--r--  1 _mysql  _mysql  9216  7 21 22:49 wp_usermeta.MYI
-rw-r--r--  1 _mysql  _mysql  8684  7 22 09:55 wp_usermeta.frm

うし。

んで、念のため一旦mysqlを再起動。

$ sudo mysql.server restart

次にmysqlにログインして、もう一度checkrepairを実行。

mysql> check table wp_usermeta medium;
+-----------------------+-------+----------+----------------------------------------------------------+
| Table                 | Op    | Msg_type | Msg_text                                                 |
+-----------------------+-------+----------+----------------------------------------------------------+
| wordpress.wp_usermeta | check | warning  | 9 clients are using or haven't closed the table properly |
| wordpress.wp_usermeta | check | status   | OK                                                       |
+-----------------------+-------+----------+----------------------------------------------------------+
2 rows in set (0.00 sec)

mysql> repair table wp_usermeta USE_FRM;
+-----------------------+--------+----------+-------------------------------------+
| Table                 | Op     | Msg_type | Msg_text                            |
+-----------------------+--------+----------+-------------------------------------+
| wordpress.wp_usermeta | repair | warning  | Number of rows changed from 0 to 23 |
| wordpress.wp_usermeta | repair | status   | OK                                  |
+-----------------------+--------+----------+-------------------------------------+
2 rows in set (0.01 sec)

mysql> check table wp_usermeta medium;
+-----------------------+-------+----------+----------+
| Table                 | Op    | Msg_type | Msg_text |
+-----------------------+-------+----------+----------+
| wordpress.wp_usermeta | check | status   | OK       |
+-----------------------+-------+----------+----------+
1 row in set (0.00 sec)mysql>

エラーメッセージが変わってます! そして復旧もできたっぽい!

ここまでできたら、あとはsqldump取得して、windows osの方へデータを送って、importしてもらって復旧できました。

まとめ

できたのはいいけど、オプションの意味がまだよくわかっていないので、これから調べてみる。