MySQL5.5.6で変なエラーに遭遇した。

MySQL5.5.6で変なエラーに遭遇した。

レプリケーションのスレーブサーバで、数日前に別の障害が発生したため、ある時点でのフルバックアップまで遡ってそこからレプリケーションをonにして追いかけてた。

その途中にエラーに詰まってしまった。

エラーの内容は下記。


Last_Errno: 1548
Last_Error: Error 'Cannot load from mysql.proc. The table is probably corrupted' on query. Default database: 'hoge'. Query: 'UPDATE hoge SET hoge_name = replaceSymbol(hoge_name)'

エラー番号でググってみるもヒットしない。まぁ公式をみても大して当てにはならない。

よくわかんないのでmysql.procを調べてみた。


*************************** 2. row ***************************
db: hoge
name: replaceSymbol
type: FUNCTION
specific_name: replaceSymbol
language: SQL
sql_data_access: CONTAINS_SQL
is_deterministic: YES
security_type: DEFINER
param_list: str TEXT charset utf8
returns: text CHARSET utf8

body: BEGIN

/* 中略 */

SET str = REPLACE(str, '\\', ' ');

RETURN str;
END
definer: [email protected]%
created: 2009-10-08 15:44:43
modified: 2009-10-08 15:44:43
sql_mode:
comment:
character_set_client: utf8
collation_connection: utf8_general_ci
db_collation: latin1_swedish_ci
body_utf8: BEGIN
SET str = REPLACE(str, '\', ' ');

/* 中略 */

SET str = REPLACE(str, ' ', '[] \\\*\+-.,\?\(\)\{\}\[\^\$\|]*');
RETURN str;
END

なるほど、ストアドプロシージャ(?)が入ってるらしい。

ストアドプロシージャの一覧を調べてみる。


mysql> use hoge;

mysql> show function status;
ERROR 1548 (HY000): Cannot load from mysql.proc. The table is probably corrupted

やっぱりダメぽ。

コレの定義がおかしいのかな、ってことで定義し直してみる。


mysql> truncate proc;
Query OK, 0 rows affected (0.00 sec)
mysql> select * from proc;
Empty set (0.00 sec)
mysq>DELIMITER $$
DROP PROCEDURE IF EXISTS `hoge`.`hoge` $$
CREATE PROCEDURE `hoge`.`hoge` ()
BEGIN
END $$
ERROR 1548 (HY000): Cannot load from mysql.proc. The table is probably corrupted

うーん参ったなぁ。procテーブルをdropしてcreateしてもダメ。

ちゃんと読み出せてるんだけどなぁ。 あまり直った試しのないrepair tableをかけてもダメ。


mysql> use mysql; repair table proc;
+------------+--------+----------+----------+
| Table      | Op     | Msg_type | Msg_text |
+------------+--------+----------+----------+
| mysql.proc | repair | status   | OK       |
+------------+--------+----------+----------+
1 row in set (0.02 sec)

この段階で他のレプリケーションからデータをコピーし終え、この問題をあきらめる決心をつけた。

一応、mysql 5.5のバージョンを上げてみる。

mysql-server-5.5.6_1 -> mysql-server-5.5.8_3

もうココまでか、残念、とか思ってたら該当する記事を見つけた。
MySQL Bugs: #52444: mysql_upgrade fails b/w 5.1 -> 5.5 (Celosia)

procのテーブル形式が違うとかそういうことなのかな。
じつはこの5.5のサーバは元々5.1で利用してて、そこのdatadirをまるまるコピーしてきてる(と思う)。
だからたぶんその辺が問題なんじゃないかな。
でもじつは同じことをこのサーバで過去にやってて、そのときは詰まらなかった。なんでだろう。

ほんでまぁ、テキトウに記事を流し読みしたら、mysql_upgradeってのにバグがあってそこのパッチこれね、とか書いてある。
え、今回も過去もそんなのをやった覚えないっす。
というわけでこれを実行してみる。

このスクリプト(バイナリでした)はmysqlサーバに接続してごにょごにょするものなのでmysqldを立てっぱでやるらしい。


shell> mysql_upgrade
Looking for 'mysql' as: mysql
Looking for 'mysqlcheck' as: mysqlcheck
Running 'mysqlcheck with default connection arguments
Running 'mysqlcheck with default connection arguments
cacti.cdef                                         OK
cacti.cdef_items                                   OK
cacti.colors                                       OK
cacti.data_input                                   OK
cacti.data_input_data                              OK

/* 中略 */

wordpress.wp_usermeta                       OK
wordpress.wp_users                          OK
Running 'mysql_fix_privilege_tables'...
OK

で、ストアドプロシージャを作成するクエリを流すと・・・


mysql> DELIMITER $$
mysql> CREATE PROCEDURE `nico`.`hoge` ()
 -> BEGIN
 ->
 -> END $$
Query OK, 0 rows affected (0.00 sec)
mysql> DELIMITER ;

おおお、なんかうまくいってる!

今回の問題は該当のストアドプロシージャがなかったので、親元から手動でコピーしてきて復元すればレプリケーションは直る、と!

これまで5.5を何の気なしに使ってきてたけど、移行するときにはちゃんとmysql_upgradeをかけてやらないとダメみたい。

メジャーバージョンアップ(になるのかな?)のときにはちゃんとその辺を調べてやってやりましょう!

またmysql_upgradeの内容については下記のリンクに書いてありました。

MySQL ::   MySQL 5.5 Reference Manual :: 4.4.7 mysql_upgrade — Check Tables for MySQL Upgrade<

乱暴にかいつまむと、

このバイナリは以下のコマンドを実行することと等価です。

mysqlcheck --all-databases --check-upgrade --auto-repair
mysql < fix_priv_tables
mysqlcheck --all-databases --check-upgrade --fix-db-names --fix-table-names

他にも移行に関する注意点など。読んでないけど・・

MySQL ::   MySQL 5.5 Reference Manual :: 2.11.1.1 Upgrading from MySQL 5.1 to 5.5

まとめ

5.1から5.5へ移行したらmysql_upgradeをかけましょう。

コメントを残す